517 Commits

Author SHA1 Message Date
bol-van
48185174cf update changes.txt 2025-12-04 14:56:29 +03:00
bol-van
aa8d903bb1 blockcheck: fix broken DNS cache 2025-12-04 14:54:19 +03:00
bol-van
cb653bedd6 blockcheck: check existense instead of curl 2025-12-02 08:54:10 +03:00
bol-van
534c88c96a fix 'which' function behavior with absolute paths 2025-12-02 08:53:38 +03:00
bol-van
7be9790839 remove obsolete file 2025-12-01 09:33:15 +03:00
bol-van
14d7f27b6a github: delete windivert filters from embedded build 2025-11-24 20:57:38 +03:00
bol-van
97cefbace9 update .gitattributes 2025-11-21 17:07:44 +03:00
bol-van
43cea80619 nfqws: fix crypto code 2025-11-18 15:14:42 +03:00
bol-van
ce7d91a7ca blockcheck: fix broken ip block tests 2025-11-15 00:22:44 +03:00
bol-van
105ac57655 add 100.64.0.0/10 to default exclude 2025-11-11 14:55:38 +03:00
bol-van
06f5305617 nfqws: remove unneeded code 2025-11-11 09:42:48 +03:00
bol-van
45c3f00539 nfqws: do not increase retrans counter every reasm piece 2025-11-11 09:39:59 +03:00
bol-van
0c0c2547db blockcheck: shield curl 2025-11-10 12:48:44 +03:00
bol-van
60d182b97e update en WSL info 2025-11-08 22:12:23 +03:00
bol-van
907b530068 update WSL info 2025-11-08 22:11:15 +03:00
bol-van
8763768180 update WSL info 2025-11-08 22:06:48 +03:00
bol-van
793cd76621 update WSL info 2025-11-08 22:05:21 +03:00
bol-van
9b47b21918 nfqws: ipv6 ah header length is in 32-bit words, not 64-bit 2025-11-08 20:46:09 +03:00
bol-van
caa364e0ed blockcheck: fix doh resolve failure if spaces in the path 2025-11-06 22:14:47 +03:00
bol-van
76992dc3d9 nfqws: remove duplicate defines 2025-11-05 17:08:34 +03:00
bol-van
0b8e0dc97d blockcheck: replace ipv6 only ntc.party to ej.ru 2025-10-30 16:19:52 +03:00
bol-van
1408c38522 blockcheck: fix - sign regression 2025-10-28 21:50:46 +03:00
bol-van
cea968d259 blockcheck: filter out : 2025-10-28 18:24:32 +03:00
bol-van
f91bca170a blockcheck: support URIs, support disabling HEAD for https 2025-10-28 14:45:15 +03:00
bol-van
9d5c9191be Merge pull request #1834 from ooovlad/fix-readme-typo
Fix the annoying typo that got me confused on my attempt to set up
2025-10-27 07:27:40 +03:00
Vlad
f4ce79a97c Fix the annoying typo that got me confused when I was trying to set up the program
Please correct this typo in the file name, as it caused me to stumble twice when setting up zapret. I took the file name directly from the readme, and then I found out that it was incorrect. Then after a while I forgot about it and took the file name from the readme again. So I decided to make a pull request.
2025-10-27 00:02:33 +03:00
bol-van
845b9edf85 Merge pull request #1821 from ilyuXer/patch-1
Update readme.md
2025-10-25 08:47:11 +03:00
ilyuXer
5ec5ce8246 Update readme.md 2025-10-24 21:01:01 +03:00
bol-van
29935b0934 update docs 2025-10-17 15:11:08 +03:00
bol-van
fe12b55181 update docs 2025-10-17 15:07:10 +03:00
bol-van
2cafc7ddeb nfqws: optimize 2025-10-17 14:35:42 +03:00
bol-van
2daf764760 nfqws: optimize 2025-10-17 14:20:54 +03:00
bol-van
078022bccf nfqws: minor bug 2025-10-17 14:15:36 +03:00
bol-van
57778b6249 nfqws: --dup-ip-id, --*-tcp-flags-*, --wssize-forced-cutoff 2025-10-17 14:10:30 +03:00
bol-van
845f4b43ef remove bad comments from custom scripts 2025-10-13 16:43:52 +03:00
bol-van
a485030423 50-quic4all 2025-10-13 16:42:59 +03:00
bol-van
6821093493 50-quic4all 2025-10-13 16:41:49 +03:00
bol-van
0dea2d6ad0 blockcheck: MIN/MAX_AUTOTTL_DELTA 2025-10-13 16:14:19 +03:00
bol-van
16e71fc5fc nfqws: fix --ip-id when changing profiles 2025-10-13 15:52:16 +03:00
bol-van
b2795989b7 update docs 2025-10-13 15:29:57 +03:00
bol-van
dbfc20a5bc nfqws: ip_id improvements 2025-10-13 14:51:42 +03:00
bol-van
2aa301bf0b update docs 2025-10-13 12:55:04 +03:00
bol-van
324aa12ecf update docs 2025-10-13 12:35:43 +03:00
bol-van
af5cf623be update docs 2025-10-13 12:35:07 +03:00
bol-van
9556eff091 update docs 2025-10-13 12:34:41 +03:00
bol-van
ca42c88ce0 update docs 2025-10-13 12:33:54 +03:00
bol-van
62cdc8bf13 nfqws: random ip_id not zero 2025-10-12 20:15:52 +03:00
bol-van
643c254fab nfqws: --ip-id 2025-10-12 20:08:08 +03:00
bol-van
3f2ef1feee windivert_part.quic_initial_ietf.txt 2025-10-12 15:23:11 +03:00
bol-van
3c8e4ed15d update docs 2025-10-12 14:35:27 +03:00
bol-van
8c06a6335d update docs 2025-10-12 14:34:49 +03:00
bol-van
f12cae3674 update docs 2025-10-12 14:34:21 +03:00
bol-van
170281bfa6 update docs 2025-10-12 14:33:16 +03:00
bol-van
5d4747458f update docs 2025-10-12 14:30:05 +03:00
bol-van
5774e883d6 update docs 2025-10-12 14:19:04 +03:00
bol-van
80b801c1ca nfqws: fix seqovl>=split_pos message 2025-10-10 17:53:14 +03:00
bol-van
9d8ee398c3 Revert "blockcheck: enable ECN in windows"
This reverts commit 4d35d8d1ec.
2025-10-08 16:32:56 +03:00
bol-van
4d35d8d1ec blockcheck: enable ECN in windows 2025-10-07 10:19:02 +03:00
bol-van
977d117417 nfqws: prevent memleak if multiple fakedsplit pattern options 2025-10-04 20:45:24 +03:00
bol-van
cc8313db51 nfqws: optimize default fakedsplit pattern 2025-10-04 20:18:39 +03:00
bol-van
1e51f90130 nfqws: fix fakedsplit-pattern if not specified 2025-10-04 19:59:19 +03:00
bol-van
da6b89e739 blockcheck: print some OPENWRT_xxx from /etc/os-release 2025-10-04 18:31:48 +03:00
bol-van
90470440a7 blockcheck: print PRETTY_NAME from /etc/os-release 2025-10-04 18:26:07 +03:00
bol-van
a5c9d79417 update docs 2025-10-04 11:58:59 +03:00
bol-van
c003ef2a7b update docs 2025-10-04 11:58:35 +03:00
bol-van
42541fcab8 update docs 2025-10-04 11:57:53 +03:00
bol-van
20b5952978 update docs 2025-10-04 11:56:07 +03:00
bol-van
4b6aa1b5f9 nfqws: help text for more altorders 2025-10-04 11:43:06 +03:00
bol-van
9e141dcefd update docs 2025-10-04 11:30:38 +03:00
bol-van
b1b992eb3f update docs 2025-10-04 11:28:29 +03:00
bol-van
2d061c911a update docs 2025-10-04 11:27:31 +03:00
bol-van
a213084188 update docs 2025-10-04 11:26:42 +03:00
bol-van
1c7ec32b96 update docs 2025-10-04 11:26:00 +03:00
bol-van
dcd9cfbb2b nfqws: ip_id fixes, more altorder support 2025-10-04 11:02:23 +03:00
bol-van
beb0692d28 quick_start: minor change 2025-10-03 10:48:23 +03:00
bol-van
140af2b741 quick_start: remove easy option 2025-10-03 10:47:40 +03:00
bol-van
f8cc109f0b nfqws: remove "file containing" from help text 2025-09-24 16:32:48 +03:00
bol-van
b4a2f44d56 remove -2b fakes 2025-09-24 16:26:39 +03:00
bol-van
14d05d8012 update docs 2025-09-24 16:25:08 +03:00
bol-van
71d5afeaf4 update docs 2025-09-24 16:24:36 +03:00
bol-van
45df8bfb09 update docs 2025-09-24 16:21:59 +03:00
bol-van
784058cf66 nfqws: support +offset@filename fake/pattern loading 2025-09-24 16:08:25 +03:00
bol-van
ce367b1a91 nfqws: optimize ip_id behavior 2025-09-24 10:31:06 +03:00
bol-van
a832c19974 blockcheck: test --dpi-desync-fakedsplit-mod=altorder=1 2025-09-23 14:20:23 +03:00
bol-van
2c14109163 update docs 2025-09-23 14:13:39 +03:00
bol-van
c467e696e3 nfqws: --dpi-desync-fakedsplit-mod=altorder 2025-09-23 14:06:23 +03:00
bol-van
528c27a01a update docs 2025-09-23 13:16:18 +03:00
bol-van
c2f1e708fc blockcheck: test split fake 2025-09-23 12:21:47 +03:00
bol-van
211a4f4673 update docs 2025-09-23 11:54:59 +03:00
bol-van
fd81053d79 nfqws: --dpi-desync-fake-tls=!+offset 2025-09-23 11:52:46 +03:00
bol-van
1bb9f260dd -2b tls fakes 2025-09-23 10:52:38 +03:00
bol-van
26f3cbd06f update docs 2025-09-23 10:52:16 +03:00
bol-van
e384f88931 nfqws: --dpi-desync-fake-tcp-mod=seq 2025-09-23 10:51:49 +03:00
bol-van
59bce0036b update docs 2025-09-22 17:39:00 +03:00
bol-van
0a48c923b8 update docs 2025-09-22 17:37:58 +03:00
bol-van
ed4782887f update docs 2025-09-22 17:37:21 +03:00
bol-van
80b6b75934 blockcheck: test hostfakesplit altorder 2025-09-22 17:18:23 +03:00
bol-van
245ce41550 nfqws: altorder mod for hostfakesplit 2025-09-22 17:06:30 +03:00
bol-van
db5dca28b0 nfqws: fix clang warnings 2025-09-22 15:06:52 +03:00
bol-van
6dad239fe3 blockcheck: fix infinite recursion on mac/bsd 2025-09-22 14:58:51 +03:00
bol-van
aa4982a526 blockcheck: working strategies intersection print for multiple domains 2025-09-22 14:49:33 +03:00
bol-van
61808b37d8 base.sh quote parameters in replace_char 2025-09-22 13:05:35 +03:00
bol-van
4b90ee920c update docs 2025-09-22 10:11:06 +03:00
bol-van
170e9d7ffd nfqws: --dpi-desync-hostfakesplit-mod 2025-09-22 09:51:25 +03:00
bol-van
d8f9ba29c3 update docs 2025-09-21 19:44:31 +03:00
bol-van
4914b813e7 update docs 2025-09-21 19:42:38 +03:00
bol-van
c3fdec9bf0 update docs 2025-09-21 18:54:38 +03:00
bol-van
1cbdf9b891 nfqws: hostfakesplit fix use-after-free 2025-09-21 18:36:49 +03:00
bol-van
706dd7b2d9 nfqws: hostfakesplit send second fake 2025-09-21 18:31:09 +03:00
bol-van
b2468a9095 blockcheck: change nft postnat hook from output to postrouting to fix some issues 2025-09-21 17:53:50 +03:00
bol-van
acfbbc58ac blockcheck: new strategies 2025-09-21 14:54:31 +03:00
bol-van
fd506dfe08 nfqws: print sessionID lengths if dupsid cannot be applied 2025-09-21 13:17:52 +03:00
bol-van
1ee25e01ea nfqws: generate random host with a-z at the first position 2025-09-21 12:51:06 +03:00
bol-van
521c385adb nfqws: --dpi-desync=hostfakesplit 2025-09-21 12:32:53 +03:00
bol-van
17971e87b4 update docs 2025-09-20 15:25:37 +03:00
bol-van
4dc1d035d8 update docs 2025-09-20 15:24:32 +03:00
bol-van
07eee8af25 winws: --wf-raw-part 2025-09-20 13:59:54 +03:00
bol-van
06e7818240 quick_start: traditional linux separate link 2025-09-04 10:12:09 +03:00
bol-van
00b0f3c940 quick_start: typo 2025-09-04 10:09:48 +03:00
bol-van
17df2adbe0 quick_start: curl/wget to stdout info 2025-09-04 10:09:01 +03:00
bol-van
40342745f7 quick_start: curl/wget to stdout info 2025-09-04 10:06:42 +03:00
bol-van
54d4cdb2d5 50-dht4all fix space/tabs 2025-09-03 17:19:35 +03:00
bol-van
b251ea839c custom scripts increase repeats 2025-09-03 12:24:00 +03:00
bol-van
595cf863fc put old kernel ver note for @ih to customs 2025-09-01 22:00:55 +03:00
bol-van
91d5b90ded install_easy: install iptables-mod-u32 2025-09-01 21:29:00 +03:00
bol-van
33a7132920 50-dht4all move from @th to @ih 2025-09-01 21:25:30 +03:00
bol-van
d9b23f14a2 docs works 2025-08-22 19:13:41 +03:00
bol-van
06613b4fd5 docs: windows server note 2025-08-22 19:10:56 +03:00
bol-van
7364bab8a7 docs works 2025-08-22 18:58:29 +03:00
bol-van
1f48453989 docs works 2025-08-22 18:56:28 +03:00
bol-van
dc5efebee2 docs works 2025-08-22 18:55:06 +03:00
bol-van
10c9499647 update changes 2025-08-22 18:51:31 +03:00
bol-van
a50082df92 readme: hardware details 2025-08-22 18:49:09 +03:00
bol-van
0c33bbfb37 readme.en: 6.17 kernel iptables notice 2025-08-22 18:38:01 +03:00
bol-van
ea1be413a6 readme.en: 6.17 kernel iptables notice 2025-08-22 18:37:03 +03:00
bol-van
850d4023fb readme: 6.17 kernel iptables notice 2025-08-22 18:33:08 +03:00
bol-van
4872b8e4e8 doc fix 2025-08-21 17:05:48 +03:00
bol-van
75eaefa950 Merge pull request #1686 from ekungurov/update-readme
doc fix
2025-08-21 17:05:08 +03:00
bol-van
582ade3190 doc fix 2025-08-21 17:00:08 +03:00
Yevgeny Kungurov
efd369bb0e doc fix 2025-08-19 18:51:35 +04:00
bol-van
784465bdcf add windivert lang desc link 2025-08-13 10:00:07 +03:00
bol-van
40a80cd328 update changes 2025-08-12 12:41:49 +03:00
bol-van
73f21b0524 discord only ipv4 2025-08-12 12:38:42 +03:00
bol-van
34698479d0 minor improve stun windivert filter 2025-08-12 11:29:27 +03:00
bol-van
0830633f42 windivert: --filter-l7 in readme.txt 2025-08-12 11:00:27 +03:00
bol-van
fc837e14fa windivert filter examples 2025-08-12 10:53:45 +03:00
bol-van
0e288262b5 wg4all note 2025-08-12 09:57:08 +03:00
bol-van
dce049d6b8 discord custom 2025-08-12 09:41:55 +03:00
bol-van
d103602d86 stun4all fix length check 2025-08-12 09:41:44 +03:00
bol-van
aaf8f18a7d optimize 50-stun4all 2025-08-12 08:48:33 +03:00
bol-van
de19cc3cd4 replace spaces with tab 2025-08-11 20:44:27 +03:00
bol-van
1e56703d4b replace spaces with tab 2025-08-11 20:43:07 +03:00
bol-van
cd0f1c4bdf stun4all, wg4all improve 2025-08-11 20:27:39 +03:00
bol-van
135b152497 stun4all, wg4all improve 2025-08-11 20:23:38 +03:00
bol-van
56456c1e0c nfqws,tpws: fix possible crashes or high memory usage if hostlist has duplicate hostnames 2025-08-08 11:35:13 +03:00
bol-van
d6a8d1dc33 lame issue warning in english 2025-08-06 08:25:23 +03:00
bol-van
04b3b6abcb update issue warning 2025-08-04 10:59:41 +03:00
bol-van
fd58ecf8a5 update issue warning 2025-08-04 10:58:41 +03:00
bol-van
a560e251a1 update changes.txt 2025-08-01 13:28:19 +03:00
bol-van
2ff0f9c0ff tpws: minor update 2025-08-01 13:23:05 +03:00
bol-van
4dbd673eaa update changes.txt 2025-08-01 12:52:06 +03:00
bol-van
497810ab4e tpws: special case for ip looking hostnames 2025-08-01 12:48:16 +03:00
bol-van
4cfed1db7e nfqws: print hostname_is_ip in ipv6 ipcache 2025-08-01 12:12:24 +03:00
bol-van
fd6b7a2b7f nfqws: optimize code 2025-08-01 12:03:53 +03:00
bol-van
6d865ad790 nfqws: comment 2025-08-01 11:31:48 +03:00
bol-van
dfe36aee4c nfqws: special case for ip looking hostnames 2025-08-01 11:21:23 +03:00
bol-van
2d704a859d blockcheck: display timestamp enable message 2025-07-31 13:57:13 +03:00
bol-van
8026d11f71 blockcheck: test ts fooling, silently enable timestamps in windows 2025-07-31 13:49:30 +03:00
bol-van
2f77cec863 doc works 2025-07-31 13:11:18 +03:00
bol-van
ba7954f068 doc works 2025-07-31 13:09:44 +03:00
bol-van
8b5c951451 nfqws: ts fooling 2025-07-31 12:51:31 +03:00
bol-van
84e75b0f28 doc works 2025-07-30 15:08:09 +03:00
bol-van
c4e5db309f doc works 2025-07-30 15:06:24 +03:00
bol-van
769f7b60c8 doc works 2025-07-30 15:02:08 +03:00
bol-van
b0578c5e9f doc works 2025-07-30 15:00:41 +03:00
bol-van
40362bfb5b doc works 2025-07-30 15:00:05 +03:00
bol-van
10eb9050a1 doc works 2025-07-30 14:59:28 +03:00
bol-van
b63e598085 FILTER_MARK support 2025-07-30 14:42:30 +03:00
bol-van
c60f9c9027 doc update ver 2025-07-08 10:01:58 +03:00
bol-van
951c980bec typo 2025-07-07 17:33:36 +03:00
bol-van
5eaec085dd install_easy: warn about --ipset 2025-07-07 15:53:46 +03:00
bol-van
721b353776 doc works 2025-07-07 15:38:51 +03:00
bol-van
e6d2051c87 doc works 2025-07-07 15:37:40 +03:00
bol-van
e665794ac4 doc works 2025-07-07 15:33:41 +03:00
bol-van
7db14a07c5 tpws: openbsd no more inits /dev/pf by default 2025-07-07 15:33:02 +03:00
bol-van
c14554c1f3 Merge pull request #1585 from artur-intech/patch-1
Fix filename
2025-06-30 07:46:10 +03:00
Artur
ced1682003 Fix filename 2025-06-29 21:45:50 +03:00
Artur
4701f27372 Fix filename
It is `zapret-hosts-user.txt`, not `*-users*`.
2025-06-29 20:18:37 +03:00
bol-van
a1699067b3 Merge pull request #1575 from dass79zh/ipv6less-curl-fix
Support curl compiled without IPv6 support.
2025-06-27 21:57:08 +03:00
Andrew Danshin
643fc0c456 Support curl compiled without IPv6 support.
modified:   blockcheck.sh
2025-06-27 21:07:32 +03:00
bol-van
09c07f6d21 winws: decrease wf-save buf 2025-06-23 08:17:52 +03:00
bol-van
dd72c68ae6 winws: increase windivert filter buffers 2025-06-23 08:14:36 +03:00
bol-van
9c1a3e77cc Makefiles: CC=cc 2025-06-22 21:39:27 +03:00
bol-van
ae957e9a73 doc fix 2025-06-22 19:27:20 +03:00
bol-van
bc47a13ba4 install_bin: no help text if getarch 2025-06-16 09:13:40 +03:00
bol-van
20b69cb63d install_bin: minor improve help text 2025-06-16 07:15:08 +03:00
bol-van
ef4f8a2b86 install_bin: display help text if no bins found 2025-06-16 07:11:59 +03:00
bol-van
d00d341505 blockcheck: display kernel ver 2025-06-15 16:22:38 +03:00
bol-van
0738d3980f blockcheck: curl version display 2025-06-15 15:56:25 +03:00
bol-van
34ff4630bf blockcheck: curl version display 2025-06-15 15:55:03 +03:00
bol-van
f8b5f602a4 nfqws: allow desync of replayed udp with reasm offset !=0 2025-06-15 09:18:25 +03:00
bol-van
8dacb57a86 OPTIMIZE in makefiles 2025-06-13 22:17:32 +03:00
bol-van
9776d5d8a9 nfqws: old gcc 4.x compat 2025-06-13 11:44:11 +03:00
bol-van
f88c9a662d nfqws: allow linux build without ssid 2025-06-13 11:31:50 +03:00
bol-van
97bcb9740d update docs 2025-06-13 11:12:37 +03:00
bol-van
b6e9fa3434 nfqws: check wext ssid len not zero 2025-06-12 13:22:54 +03:00
bol-van
32cfee705a nfqws: optimize wext 2025-06-12 11:58:20 +03:00
bol-van
1303bf0fef update changes.txt 2025-06-12 11:46:34 +03:00
bol-van
2417d4ee76 nfqws: use wireless ext in case nl80211 does not return ssid 2025-06-12 11:45:14 +03:00
bol-van
64280cbf3d doc works 2025-06-12 09:08:21 +03:00
bol-van
54dd06056e doc works 2025-06-12 09:06:06 +03:00
bol-van
0be4cbf8a4 rename windows bin dirs 2025-06-11 21:28:18 +03:00
bol-van
acf888c493 rename android bin dir 2025-06-11 21:26:32 +03:00
bol-van
f3d90d4e00 rename freebsd bin dir 2025-06-11 21:25:14 +03:00
bol-van
ceec80a8ed openwrt makefile -lmnl 2025-06-11 20:52:12 +03:00
bol-van
e876096072 rename bin dirs 2025-06-11 20:49:46 +03:00
bol-van
796e4a40b6 rename bin dirs 2025-06-11 20:48:51 +03:00
bol-van
5b7c4a4318 rename bin dirs 2025-06-11 20:46:53 +03:00
bol-van
f09d918b40 nfqws,tpws: use initgroups() if --user specified 2025-06-11 20:15:43 +03:00
bol-van
f3d48b7160 nfqws: debug wlan info init 2025-06-04 10:05:42 +03:00
bol-van
58d306b552 nfqws: --filter-ssid (linux only) 2025-06-04 09:26:38 +03:00
bol-van
30a947b42b install_bin.sh : minor bug 2025-06-01 19:16:37 +03:00
bol-van
9fe26c92a5 install_bin: remove quarantine xattr on macos 2025-06-01 15:30:51 +03:00
bol-van
ab0d16f4e1 install_easy: fix broken compile on mac 2025-06-01 09:11:33 +03:00
bol-van
c37c39996d static 2025-05-31 13:42:36 +03:00
bol-van
87a0cf0797 nfqws,tpws: --debug=android for NDK builds 2025-05-31 10:34:03 +03:00
bol-van
893a133f86 install_easy: rephrase 2025-05-30 10:54:20 +03:00
bol-van
fa9e3c09f1 install_easy: ask MODE_FILTER before daemon test 2025-05-29 19:14:35 +03:00
bol-van
2edf6bee34 install_easy: minor fix 2025-05-29 19:05:50 +03:00
bol-van
468d293b46 install_easy: run daemon test under proper user 2025-05-29 19:02:50 +03:00
bol-van
fd698d801b nfqws,tpws: check list files accessibility with dropped privs in --dry-run mode 2025-05-29 15:43:27 +03:00
bol-van
38a3833351 install_bin: do exec test after elf test 2025-05-28 23:06:12 +03:00
bol-van
6c9ff2010b install_bin: fix TEST=run 2025-05-28 22:46:55 +03:00
bol-van
06f57e27ed install_bin: fix minor problems 2025-05-28 20:40:26 +03:00
bol-van
06921bdbee install_bin: read elf detection method 2025-05-28 20:27:34 +03:00
bol-van
3999e0b350 install_bin: read elf detection method 2025-05-28 20:22:09 +03:00
bol-van
1301aca25b Upx 5.0.1 still has bugs on mips
This reverts commit f0a8a35c12.
2025-05-28 19:37:57 +03:00
bol-van
bf4244809f install_easy: stop if running embedded release on traditional linux 2025-05-28 14:37:32 +03:00
bol-van
99b5406905 redsocks: shell /bin/false 2025-05-27 22:24:58 +03:00
bol-van
ebd01868ee redsocks: no bash for su 2025-05-27 22:20:46 +03:00
bol-van
c451addd86 redsocks: shadow-su 2025-05-27 21:53:44 +03:00
bol-van
4c8ea084d7 redsocks.txt: remove obsolete 2025-05-27 21:46:46 +03:00
bol-van
02badb3c4c nfqws,tpws: move --ipset to kavl 2025-05-27 16:03:28 +03:00
bol-van
323307cbfa Merge pull request #1464 from Dronatar/patch-1
Omission fix in readme.md
2025-05-26 09:38:57 +03:00
Dronatar
00560719bd Omission fix in readme.md 2025-05-26 06:15:29 +02:00
bol-van
56c96df47b remove seccomp from systemd units 2025-05-25 20:07:52 +03:00
bol-van
f0a8a35c12 They fixed problems
This reverts commit 58e73d0331.
2025-05-25 09:49:01 +03:00
bol-van
d566f48f94 blockcheck: display ip version every test 2025-05-24 13:35:11 +03:00
bol-van
3513cbb65e winws: fix trash flood warning message 2025-05-24 10:51:01 +03:00
bol-van
20f91cb7ab doc works 2025-05-24 09:58:41 +03:00
bol-van
4becc07572 update changes 2025-05-22 11:01:34 +03:00
bol-van
a39c18737b nfqws: - disables autottl 2025-05-22 11:00:11 +03:00
bol-van
ed7b743fe2 update changes.txt 2025-05-22 10:44:26 +03:00
bol-van
d3b0b3e0b1 nfqws,tpws: display android in version string 2025-05-22 10:19:30 +03:00
bol-van
ba040769a7 doc works 2025-05-21 17:40:46 +03:00
bol-van
0ced50e393 doc works 2025-05-21 17:39:50 +03:00
bol-van
f3abd6815a doc works 2025-05-20 19:07:42 +03:00
bol-van
4572799750 doc works 2025-05-20 19:06:48 +03:00
bol-van
696167509a doc works 2025-05-20 19:03:47 +03:00
bol-van
2374df6d74 doc works 2025-05-20 19:02:22 +03:00
bol-van
ab06d6b640 doc works 2025-05-20 19:01:14 +03:00
bol-van
60efab1cc6 doc works 2025-05-20 18:57:46 +03:00
bol-van
71aebbb4d3 nfqws: allow zero autottl 2025-05-20 18:06:56 +03:00
bol-van
c993f117a2 blockcheck: test http3 google fake 2025-05-20 12:05:43 +03:00
bol-van
b2f0c46388 update changes.txt 2025-05-20 11:32:58 +03:00
bol-van
2b095f863f blockcheck: report test function and domain every test 2025-05-20 11:32:08 +03:00
bol-van
a141dff374 nfqws: warn dup trash flood 2025-05-20 10:30:37 +03:00
bol-van
b34bfda8b5 blockcheck: tls multi fake test 2025-05-10 18:12:51 +03:00
bol-van
c1046a20db nfqws,tpws: sec_harden after daemonize 2025-05-10 16:57:04 +03:00
bol-van
24b93cca7e blockcheck: some dup and orig-autottl mods 2025-05-10 15:58:36 +03:00
bol-van
4f0fdb24f2 nfqws,tpws: support multiple gids in --uid 2025-05-10 11:11:56 +03:00
bol-van
6d52b49b98 nfqws: do not reconstruct synack-split in syn mode 2025-05-10 09:41:26 +03:00
bol-van
4b632313e2 nfqws: improve --synack-split 2025-05-09 20:57:14 +03:00
bol-van
22f3ecaec1 doc works 2025-05-09 20:41:02 +03:00
bol-van
2a23bc99f6 nfqws: --synack-split select syn or ack first 2025-05-09 20:20:55 +03:00
bol-van
8a1d7c7abd doc works 2025-05-09 17:21:08 +03:00
bol-van
ba712f308d doc works 2025-05-09 17:19:46 +03:00
bol-van
9ace0328ad doc works 2025-05-09 17:18:44 +03:00
bol-van
5c6f79799a doc works 2025-05-09 16:45:00 +03:00
bol-van
a84d015b1e doc works 2025-05-09 16:44:08 +03:00
bol-van
2d90a28dbc Revert "doc works"
This reverts commit 3c77bab002.
2025-05-09 16:42:17 +03:00
bol-van
3c77bab002 doc works 2025-05-09 16:22:21 +03:00
bol-van
8f27725d6a nfqws: --synack-split 2025-05-09 16:20:28 +03:00
bol-van
729ded0c61 nfqws: conntrack workaround TTL=1 2025-05-09 11:17:21 +03:00
bol-van
691a501b0d nfqws,tpws: do most checks before daemonize 2025-05-09 10:32:19 +03:00
bol-van
e62fb2f0f4 nfqws: simplify conntrack workaround 2025-05-08 19:46:35 +03:00
bol-van
603265dac2 nfqws: do not realloc hostname in ipcache if it's the same 2025-05-08 13:45:28 +03:00
bol-van
ed0bb4c106 tpws: ipcache socks hostname 2025-05-08 13:42:24 +03:00
bol-van
6eae2b0e71 doc works 2025-05-08 12:23:51 +03:00
bol-van
c59771f744 doc works 2025-05-08 12:20:55 +03:00
bol-van
dd23d6f3f4 doc works 2025-05-08 12:08:38 +03:00
bol-van
92dc012f08 doc works 2025-05-08 12:01:04 +03:00
bol-van
9bcefde37a doc works 2025-05-08 11:45:50 +03:00
bol-van
d2f7a53927 nfqws: --ctrack-disable 2025-05-08 09:00:20 +03:00
bol-van
f1dd351854 nfqws: --ctrack-disable 2025-05-08 08:54:05 +03:00
bol-van
5c63cb43e7 readme: update vps section 2025-05-06 09:58:03 +03:00
bol-van
7f24f82002 readme: update vps section 2025-05-06 09:51:53 +03:00
bol-van
b0c7af789a init: remove autohostlist touch, not needed anymore 2025-05-04 22:02:36 +03:00
bol-van
a426ea6dad nfqws,tpws: check list files accessibility after all params are parsed 2025-05-04 22:01:00 +03:00
bol-van
bda4226162 init: create autohostlist file if not exists 2025-05-04 21:47:26 +03:00
bol-van
dc1dc5c876 drop time exceeded icmp for nfqws-related connections 2025-05-04 18:21:43 +03:00
bol-van
3ca682e25a drop time exceeded icmp for nfqws-related connections 2025-05-04 18:15:33 +03:00
bol-van
9629ce5cb7 tpws: ipcache 2025-05-04 10:57:23 +03:00
bol-van
c626d88f54 nfqws: minor changes 2025-05-04 10:42:27 +03:00
bol-van
c91ddf4a54 nfqws: do not use interface name for ip->hostname 2025-05-03 22:06:14 +03:00
bol-van
6f1286b5b9 nfqws: fix mem leak 2025-05-03 21:59:43 +03:00
bol-van
c96bc62d3b nfqws: ip->hostname cache 2025-05-03 20:25:53 +03:00
bol-van
8432388b37 nfqws: debug autottl cache lifetime 2025-05-03 15:15:26 +03:00
bol-van
7efa83e61e init.d: remove --ipset prohibition 2025-05-03 13:03:33 +03:00
bol-van
abe91a4bfa nfqws: ipcache destroy in cleanup_params 2025-05-03 12:50:53 +03:00
bol-van
43173e6396 nfqws: return autottl path len check 2025-05-03 12:28:49 +03:00
bol-van
5cc888cd2c nfqws: autottl cache, --dup-autottl, --orig-autottl 2025-05-03 12:11:16 +03:00
bol-van
5b625fa709 update nftables.txt,iptables.txt 2025-05-03 10:54:59 +03:00
bol-van
0a8135b2de update config defaults 2025-05-03 10:52:20 +03:00
bol-van
d21175b4a3 nfqws: prepare for +- autottl 2025-04-29 17:45:34 +03:00
bol-van
68a538daed nfqws: conntrack: do not reset entry on dup SA 2025-04-29 16:31:37 +03:00
bol-van
d2c9ff50cd nfqws: copy DF ip flag 2025-04-29 13:36:05 +03:00
bol-van
50539d6cbf nfqws: windows fixes for recent changes 2025-04-29 12:25:23 +03:00
bol-van
8b5dfcfae1 nfqws: dup,orig_mod 2025-04-26 19:48:35 +03:00
bol-van
ccc60b5f07 init.d: fix missing - sign in 50-nfqws-ipset 2025-04-22 19:28:14 +03:00
bol-van
7f94f42b1d init.d: fix local var name 2025-04-22 19:07:26 +03:00
bol-van
1c1f259b39 init.d: improve nfqws ipset example 2025-04-22 19:03:18 +03:00
bol-van
6ef6c8ee5a nfqws: do not use overlapping memcmp 2025-04-21 15:54:06 +03:00
bol-van
581badfb73 nfqws: --dpi-desync-fake-tls=! 2025-04-21 14:52:51 +03:00
bol-van
8fce75daa4 hardware offload: be closer to fw4 in interface names 2025-04-20 11:26:07 +03:00
bol-van
c1e2e56576 hardware offload: be closer to fw4 in interface names 2025-04-20 11:24:55 +03:00
bol-van
e16ec69922 nfqws: fix unitialized use of host buffer (udp) 2025-04-20 08:49:50 +03:00
bol-van
63256a142f nfqws: fix unitialized use of host buffer 2025-04-19 19:59:42 +03:00
bol-van
4a9a8bd48e typo 2025-04-19 19:41:40 +03:00
bol-van
b996abd5ce nfqws,tpws: use tls record length in TLSDebug 2025-04-14 12:18:07 +03:00
bol-van
12461de3b0 nfqws,tpws: optimize tls debug, show quic 2025-04-14 11:21:16 +03:00
bol-van
7dab497b57 nfqws,tpws: optimize tls debug, show quic 2025-04-14 11:20:20 +03:00
bol-van
41dbba1c4c nfqws,tpws: debug alpn and ech 2025-04-13 18:07:46 +03:00
bol-van
d19f6c19a4 nfqws,tpws: debug tls version 2025-04-13 15:27:50 +03:00
bol-van
b12b1a5a17 winws build fix 2025-04-08 17:33:14 +03:00
bol-van
8022e2576d nfqws: BSD/clang build fix 2025-04-08 17:23:15 +03:00
bol-van
f4ea264ba9 minor var spelling fix 2025-04-08 17:02:33 +03:00
bol-van
061acb27e4 Merge pull request #1334 from tie/master
use enum for option indices
2025-04-08 17:00:53 +03:00
Ivan Trubach
8eb830d304 use enum for option indices 2025-04-08 16:56:17 +03:00
bol-van
2fb93c6add blockcheck: test tpws exists 2025-04-08 16:17:40 +03:00
bol-van
ad5c246629 blockcheck: test whether tpws supports fix-seg 2025-04-08 16:15:06 +03:00
bol-van
58e73d0331 github actions: do not use broken upx 5.0.0 2025-04-07 17:52:11 +03:00
bol-van
9ebeff621a readme.en : update ver 2025-04-07 10:16:30 +03:00
bol-van
69df271a16 readme: update crypto addresses 2025-04-07 10:15:36 +03:00
bol-van
e285b2401d isakmp fake 2025-04-06 16:42:56 +03:00
bol-van
6e1e7e43bc nfqws: optimize tls mod parse 2025-04-06 11:53:57 +03:00
bol-van
d04419a60c nfqws: safety check 2025-04-06 11:43:25 +03:00
bol-van
fc1bf47e82 update changes.txt 2025-04-06 11:34:43 +03:00
bol-van
929df3f094 nfqws: support different tls mods for every tls fake 2025-04-06 11:29:58 +03:00
bol-van
7272b243cb blockcheck: optimize 2025-04-05 18:13:16 +03:00
bol-van
72d48d957a update changes.txt 2025-04-05 18:10:46 +03:00
bol-van
f4069d484a update changes.txt 2025-04-05 18:10:18 +03:00
bol-van
1c82b0a6af blockcheck: --fix seg only if multiple split pos 2025-04-05 16:35:26 +03:00
bol-van
c08e69aa65 blockcheck: --fix seg only if multiple split pos 2025-04-05 16:31:22 +03:00
bol-van
8097f08020 ipset: some pkill's do not support multiple patterns 2025-04-05 13:56:31 +03:00
bol-van
4cae291e6f blockcheck: remove fix-seg for single split 2025-04-05 12:32:16 +03:00
bol-van
82ad5508dc blockcheck: --fix-seg for tpws multisplits 2025-04-05 12:24:43 +03:00
bol-van
fa8ddcfc79 desync.h fix 2025-04-05 11:53:59 +03:00
bol-van
b560e32e18 nfqws: update default tls fake 2025-04-05 09:45:44 +03:00
bol-van
67e1aee8a8 update compile docs 2025-04-04 17:38:52 +03:00
bol-van
1d8385a9b4 update compile docs 2025-04-04 17:37:49 +03:00
bol-van
340dec62a7 update changes.txt 2025-04-04 15:13:58 +03:00
bol-van
db4585c02f remove discord custom 2025-04-04 15:03:06 +03:00
bol-van
e792ca67ef nfqws: display original SNI value 2025-04-04 14:32:37 +03:00
bol-van
e5e53db6b8 nfqws: fixes 2025-04-04 14:20:36 +03:00
bol-van
e14ee9d1fe nfqws: fix wrong and mask 2025-04-04 14:09:45 +03:00
bol-van
360506ba4e discord and stun fakes 2025-04-04 13:58:46 +03:00
bol-van
aa769e05c6 nfqws: minor optimize 2025-04-04 13:58:33 +03:00
bol-van
6b0bc7a96b nfqws: tls mod set sni 2025-04-04 13:24:02 +03:00
bol-van
93bdfdb6be nfqws: loop for multiple blob cleanup 2025-04-04 09:25:46 +03:00
bol-van
6d95eada2b Merge pull request #1316 from tie/master
nfqws: also add stun l7proto to CLI help output
2025-04-03 21:33:39 +03:00
bol-van
e452ee8688 nfqws: cosmetics 2025-04-03 21:32:28 +03:00
bol-van
6e746f94cd nfqws: help text cosmetics 2025-04-03 21:29:38 +03:00
Ivan Trubach
9fd61e5d38 nfqws: also add stun l7proto to CLI help output 2025-04-03 21:28:46 +03:00
bol-van
0c0fba4461 Merge pull request #1314 from tie/master
nfqws: detect Discord Voice IP Discovery and STUN packets
2025-04-03 21:27:10 +03:00
Ivan Trubach
056e4c588a nfqws: detect STUN message packets 2025-04-03 21:02:42 +03:00
Ivan Trubach
4b288643ac nfqws: detect Discord Voice IP Discovery packets 2025-04-03 17:55:02 +03:00
bol-van
cbdee74e5f Merge pull request #1301 from Lost-gamer/master
update discord subnets
2025-04-01 10:25:22 +03:00
bol-van
743eb5a4a2 tpws makefile support systemd target for old systems 2025-03-31 16:26:00 +03:00
Lost
4e8e3a9ed9 update discord subnets 2025-03-31 10:25:52 +03:00
bol-van
b9b91a0e68 replace tls fake google 2025-03-26 12:09:49 +03:00
bol-van
9de7b66eef update build docs 2025-03-25 13:44:27 +03:00
bol-van
a2ffa3455d nfqws: minor beautify text 2025-03-24 11:20:51 +03:00
bol-van
60b97dbed0 nfqws: remove debug printfs 2025-03-24 11:14:38 +03:00
bol-van
e56e4f5f35 update changes 2025-03-24 10:32:02 +03:00
bol-van
5305ea83c8 fakes: GGC kyber with inter-packet CRYPTO frag 2025-03-24 09:44:50 +03:00
bol-van
14b3dd459b nfqws: define reasm buffer sizes 2025-03-24 09:34:37 +03:00
bol-van
66fda2c33d nfqws: support QUIC multi packet CRYPTO fragmentation 2025-03-23 23:29:16 +03:00
bol-van
77df43b9cb nfqws: minor optimize 2025-03-22 13:03:31 +03:00
bol-van
85f2b37c88 update docs 2025-03-21 21:00:47 +03:00
bol-van
e2d600fcc6 update docs 2025-03-21 20:58:53 +03:00
bol-van
37eda0ad98 nfqws: mod skipped DLOG_ERR -> DLOG 2025-03-21 19:40:25 +03:00
bol-van
770be21e1c nfqws: fix custom tls fake fallback logic 2025-03-21 19:09:37 +03:00
bol-van
1b880d42f9 nfqws,tpws: missing va_end 2025-03-21 17:33:57 +03:00
bol-van
6387315c0b nfqws: multiple fakes 2025-03-21 17:12:36 +03:00
bol-van
3d4b395bfe ignore windivert files in nfq 2025-03-21 14:23:19 +03:00
bol-van
55950ed7d0 remove bad files 2025-03-21 14:22:28 +03:00
bol-van
f2b0341484 blockcheck: add dupsid to tls-mod 2025-03-20 18:14:35 +03:00
bol-van
b2d89c5d22 blockcheck: warn MTU overflow with md5sig 2025-03-17 09:39:33 +03:00
bol-van
778b611f86 readme: md5sig with fakedsplit/fakeddisorder warning 2025-03-16 17:06:24 +03:00
bol-van
ffaf91c251 nfqws: debug packet length in sendto() 2025-03-16 15:56:47 +03:00
bol-van
326b42fafd nfqws: debug packet length in sendto() 2025-03-16 15:52:50 +03:00
bol-van
94d4238af2 update changes.txt 2025-03-14 11:41:52 +03:00
bol-van
15e22fa1bd tpws: detect WSL 1 and warn about non-working options 2025-03-14 11:38:52 +03:00
bol-van
bd8decddc5 nfqws,tpws: separate droproot from dropcaps 2025-03-13 21:54:28 +03:00
bol-van
2db1ebafe3 tpws systemd unit fix comment 2025-03-12 18:14:43 +03:00
bol-van
33bcf6f7b4 systemd improve cheat sheet 2025-03-12 17:47:17 +03:00
bol-van
f037f1acb2 update docs 2025-03-12 17:45:19 +03:00
bol-van
cdd9b32b27 update docs 2025-03-12 17:44:04 +03:00
bol-van
7934125c09 init.d: systemd unit examples for tpws and nfqws 2025-03-12 17:27:55 +03:00
bol-van
6493d55977 tpws: move systemd notify deeper 2025-03-12 14:45:52 +03:00
bol-van
cafbb17e70 install_easy: make systemd if systemd detected 2025-03-12 14:32:00 +03:00
bol-van
9ac73f7d2f readme.eng: hostlist ^ note 2025-03-12 13:07:29 +03:00
bol-van
08a6e8e069 nfqws,tpws : rename function 2025-03-12 13:03:33 +03:00
bol-van
644a934099 nfqws.service : add special compile warning 2025-03-12 12:58:36 +03:00
bol-van
0eec445af0 Merge pull request #1237 from tie/systemd
nfqws: add support for systemd readiness notifications
2025-03-12 12:50:02 +03:00
bol-van
b8acc1b979 Revert "Revert "Revert "nfqws,tpws: fflush stdin,stdout"""
This reverts commit 123eb057ae.
2025-03-12 12:49:06 +03:00
bol-van
123eb057ae Revert "Revert "nfqws,tpws: fflush stdin,stdout""
This reverts commit 56d06456fb.
2025-03-12 12:48:32 +03:00
bol-van
56d06456fb Revert "nfqws,tpws: fflush stdin,stdout"
This reverts commit a6efe05aa6.
2025-03-12 12:48:18 +03:00
bol-van
a6efe05aa6 nfqws,tpws: fflush stdin,stdout 2025-03-12 12:13:53 +03:00
Ivan Trubach
a1d29b0c3a nfqws,tpws: always use line buffering for console IO
Forces stdout and stderr to always use line buffering. Note that glibc
does automatically flush on newline iff connected to a terminal, but
that is not the case when running under systemd. See also
https://www.gnu.org/software/libc/manual/html_node/Buffering-Concepts.html
https://www.gnu.org/software/libc/manual/html_node/Controlling-Buffering.html
2025-03-12 12:00:28 +03:00
Ivan Trubach
756603338b nfqws,tpws: add support for systemd readiness notifications 2025-03-12 11:39:03 +03:00
bol-van
8b73e2ea8e update docs 2025-03-06 16:07:44 +03:00
bol-van
2a0e952153 update docs 2025-03-06 16:06:55 +03:00
bol-van
1065202349 nfqws,tpws: ^ prefix in hostlist disables subdomain matches 2025-03-06 15:13:40 +03:00
bol-van
307d38f6af readme: update ver 2025-02-26 10:04:26 +03:00
bol-van
8ac4fc0af5 fix wrong var 2025-02-26 01:11:07 +03:00
bol-van
af89d03118 nfqws,tpws: fix hostlist-domains file open test 2025-02-25 13:07:38 +03:00
bol-van
d89daaaeac add localhost to zapret-hosts-user-exclude.txt 2025-02-24 13:10:54 +03:00
bol-van
f62b289cb5 nfqws,tpws: --version 2025-02-05 13:04:24 +03:00
bol-van
5f9fa28251 nfqws,tpws: r/o open instead of stat() for list file check 2025-02-04 23:28:18 +03:00
bol-van
bd67b41f32 nfqws,tpws: check accessibility of list files after droproot 2025-02-03 22:37:08 +03:00
bol-van
00619c8dab nfqws,tpws: show hostlist/ipset stat() error 2025-02-02 22:48:23 +03:00
bol-van
58e26c3e9d Merge pull request #1128 from Yoti/patch-1
quick_start: fix spelling
2025-01-30 22:31:37 +03:00
Yoti
eddbc3c3e0 quick_start: fix spelling 2025-01-30 22:20:15 +03:00
bol-van
2cc73de15c readme: move ip2net/mdig chapters 2025-01-30 12:09:34 +03:00
bol-van
9762f2d22b update docs 2025-01-30 12:03:57 +03:00
bol-van
8c9aa188c3 readme: update flow offload info 2025-01-29 14:57:55 +03:00
bol-van
2f151c0943 readme: update flow offload info 2025-01-29 14:55:11 +03:00
bol-van
9498456c4a readme: update flow offload info 2025-01-29 14:47:20 +03:00
bol-van
860607bce2 config.default: remove obsolete comment 2025-01-29 13:42:34 +03:00
bol-van
94f59511f0 update docs 2025-01-28 21:25:44 +03:00
bol-van
b07ce8d8ca nfqws: --dpi-desync-fake-tls-mod=dupsid 2025-01-28 21:22:33 +03:00
bol-van
6fc4e75d89 changes.txt update 2025-01-28 13:28:22 +03:00
bol-van
fb894a8e2c blockcheck: add tlsmod test 2025-01-28 13:26:33 +03:00
bol-van
86352430d4 nfqws: fix slen=0 case 2025-01-28 13:01:47 +03:00
bol-van
e5f20d05f6 nfqws: fix minor clang warning 2025-01-28 12:45:35 +03:00
bol-van
b610f08a9c readme: minor change help text 2025-01-28 12:43:04 +03:00
bol-van
8bbd2d97d5 nfqws: minor change help text 2025-01-28 12:42:31 +03:00
bol-van
972f665d88 update issues 2025-01-28 12:12:36 +03:00
bol-van
a9a497fa77 Update issue templates 2025-01-28 12:09:15 +03:00
bol-van
14a170c9a3 update issue_template 2025-01-28 12:01:04 +03:00
bol-van
d4080b6c6f Merge pull request #1117 from spvkgn/elf-cleaner
github: use termux-elf-cleaner to strip unwanted ELF sections
2025-01-28 11:56:51 +03:00
bol-van
20f1fb2cfd update docs 2025-01-28 11:54:14 +03:00
bol-van
35c3216287 update docs 2025-01-28 11:41:42 +03:00
spvkgn
628f629c49 github: run termux-elf-cleaner 2025-01-28 12:53:44 +05:00
bol-van
33d3059dc8 nfqws: --dpi-desync-fake-tls-mod 2025-01-27 21:08:12 +03:00
bol-van
f5cf7917fb nfqws,tpws: file_mod_signature zero struct if unsuccessful 2025-01-24 20:57:12 +03:00
bol-van
b39508de7f Merge pull request #1056 from chymaboy/patch-4
Update readme.md OpenWrt
2025-01-24 20:52:01 +03:00
bol-van
c69a92f901 update readme 2025-01-24 12:55:16 +03:00
bol-van
aba1fdeb04 tpws,nfqws: track file size in addition to mod time 2025-01-24 12:50:17 +03:00
bol-van
02c76a4fb6 ipset: return HUP reload 2025-01-24 11:39:13 +03:00
bol-van
2ff6ec03aa tpws,nfqws: return lists reload on HUP 2025-01-24 11:12:56 +03:00
bol-van
80a0b38295 install_easy: support dnf packager 2025-01-23 14:34:54 +03:00
bol-van
e0e935c2ae nfqws: apply split+seqovl only to the first reasm fragment 2025-01-19 11:58:31 +03:00
Evgeny
31cf106728 Update readme.md
fix parameter
2025-01-14 13:37:36 +03:00
Evgeny
502e34a96d Update readme.md OpenWrt
change all repeats in text to correct registr
2025-01-14 13:35:03 +03:00
bol-van
29ab747e5b nfqws: weaken wireguard initiation recognition 2025-01-13 18:25:15 +03:00
bol-van
b897ec5d9a Merge pull request #1042 from chymaboy/patch-3
Update readme.md раздел Как это работает
2025-01-11 21:56:09 +03:00
Evgeny
440878cb9f Update readme.md
ё
2025-01-11 21:26:46 +03:00
Evgeny
1935473bd1 Update readme.md раздел Как это работает
пробелы, регистры, дефисы
2025-01-11 19:06:00 +03:00
bol-van
de6cadf8e4 readme.md: minor 2025-01-10 18:39:56 +03:00
bol-van
d509497bb8 Merge pull request #1018 from chymaboy/patch-2
Update readme.md
2025-01-10 18:38:39 +03:00
Evgeny
d7949f70b1 Update readme.md
отмена дифов:
- прежде всего
- embedded устройства
- прикрутка
2025-01-10 18:14:36 +03:00
bol-van
0912b7d104 tpws: remove unneeded header 2025-01-09 19:01:29 +03:00
bol-van
29ff997a3f nfqws,tpws: remove null pointer checks before free() 2025-01-09 18:56:01 +03:00
bol-van
f21bd0c63c update git files 2025-01-05 15:09:47 +03:00
bol-van
41693b1008 blockcheck: minor old shell compat 2025-01-05 12:52:37 +03:00
bol-van
d000345043 blockcheck: SKIP_IPBLOCK, remove hardcoded ports 2025-01-04 18:11:49 +03:00
bol-van
f986da9ae2 blockcheck: wait for child processes on terminate 2025-01-04 09:11:30 +03:00
bol-van
c6e729b237 blockcheck: CURL_MAX_TIME_DOH 2025-01-03 15:11:11 +03:00
bol-van
12a800db97 blockcheck: use defaults if BATCH=1 2025-01-03 14:40:02 +03:00
bol-van
5e84656707 blockcheck: BATCH var 2025-01-03 14:06:21 +03:00
bol-van
e87965cd2f update doc 2025-01-03 13:58:25 +03:00
bol-van
4585cc4656 blockcheck: batch mode, parallel scan 2025-01-03 13:55:32 +03:00
Evgeny
c0a08d3353 Update readme.md
Исправления текста в разделе "Зачем это нужно"
2025-01-02 12:34:14 +03:00
bol-van
77474c9f76 update readme.md 2025-01-02 10:43:15 +03:00
bol-van
15b2ee2d82 Merge pull request #1017 from chymaboy/patch-1
Update readme.md
2025-01-02 10:39:56 +03:00
Evgeny
709279d6cf Update readme.md
Небольшие улучшения текста без изменений логики: исправления опечаток, орфографических и пунктуационных ошибок.
2025-01-02 00:10:20 +03:00
bol-van
35d676406c update docs 2024-12-26 22:04:33 +03:00
bol-van
9aff90b466 nfqws: allow partial TLS for relative markers 2024-12-26 13:46:12 +03:00
bol-van
bc463930aa Merge pull request #989 from Hi-Angel/march=native
Use `-march=native` when building from install_easy.sh
2024-12-24 19:29:10 +03:00
Konstantin Kharlamov
6fe9471077 Use -march=native when building from install_easy.sh
install_easy.sh is used for local installation, which implies that if
it invokes make, the binaries are not being cross-compiled. That
allows us to pass `-march=native` to make sure the binaries are
optimized for the current CPU.

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

4
.gitattributes vendored
View File

@@ -1,5 +1,5 @@
* text=auto eol=lf
binaries/win64/readme.txt eol=crlf
binaries/win32/readme.txt eol=crlf
*.cmd eol=crlf
*.bat eol=crlf
init.d/windivert.filter.examples/** eol=crlf
files/** binary

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

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

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

@@ -0,0 +1,25 @@
---
name: bugs
about: do not write lame questions
title: ''
labels: ''
assignees: ''
---
Issues - это место для обращений к разработчику.
Discussions - место для обсуждения вопросов между пользователями.
Не тратье время разработчика на ерунду. Вам не будут здесь обьяснять как скопировать, что "писать в", почему сразу же закрывается окно, почему не открывается сайт или госуслуги. Здесь не место обсуждению любых шаманств , т.е. манипуляций без понимания, в стиле 4pda.
Пишите только конкретные проблемы на техническом уровне в оригинальном zapret (не в сборках), которые вы заметили, и которые являются или могут являться багами в софте.
Или если вы считаете, что ваше обращение обосновано, технически грамотно и по адресу.
Все, что будет нарушать эти критерии, может быть молча удалено, закрыто или перенесено в дискуссии на усмотрение разработчика.
Если сомневаетесь - пишите лучше сразу в дискуссии.
Прочитайте для начала docs/quick_start.md или docs/quick_start_windows.md.
Там обьясняется для кого этот софт, какие требуются знания, почему это не простая волшебная таблетка.
Вирусов здесь нет. У вас либо чья-то сборка, либо ваш антивирус давно пора отправить на покой. Антивирусы в основном жалуются на upx и windivert, которые убраны НЕ будут. upx - это паковщик для сокращения требуемого места на openwrt, windivert - замена iptables для windows, потенциальный инструмент хакера или компонент зловредной программы, но сам по себе вирусом не является. Не согласны - удаляйте софт. За агрессивные наезды "почему автор распространяет вирусы" молча схватите бан.
Here is the place for bugs only. All questions, especially user-like questions (non-technical) go to Discussions.
There're also no viruses here. All virus claims and everyting non-technical and non-bugs will be instantly deleted, closed or moved to Discussions.

View File

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

View File

@@ -22,9 +22,6 @@ jobs:
fail-fast: false
matrix:
include:
- arch: lexra
tool: mips-linux
dir: rsdk-4.6.4-5281-EB-3.10-0.9.33-m32ub-20141001
- arch: arm64
tool: aarch64-unknown-linux-musl
- arch: arm
@@ -55,6 +52,13 @@ jobs:
tool: i586-unknown-linux-musl
- arch: x86_64
tool: x86_64-unknown-linux-musl
- arch: lexra
tool: mips-linux
dir: rsdk-4.6.4-5281-EB-3.10-0.9.33-m32ub-20141001
env:
CFLAGS: '-march=5281'
LDFLAGS: '-lgcc_eh'
repo: 'bol-van/build'
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -63,27 +67,31 @@ jobs:
- name: Set up build tools
env:
REPO: 'spvkgn/musl-cross'
REPO_LEXRA: 'bol-van/build'
ARCH: ${{ matrix.arch }}
TOOL: ${{ matrix.tool }}
DIR: ${{ matrix.dir }}
REPO: ${{ matrix.arch == 'lexra' && matrix.repo || 'spvkgn/musl-cross' }}
DIR: ${{ matrix.arch == 'lexra' && matrix.dir || matrix.tool }}
run: |
DIR=${DIR:-$TOOL}
[ "$ARCH" = lexra ] && sudo dpkg --add-architecture i386
sudo apt update -qq
sudo apt install -y libcap-dev
[ "$ARCH" = lexra ] && sudo apt install -y libc6:i386 zlib1g:i386
if [[ "$ARCH" == lexra ]]; then
sudo dpkg --add-architecture i386
sudo apt update -qq
sudo apt install -y libcap-dev libc6:i386 zlib1g:i386
URL=https://github.com/$REPO/raw/refs/heads/master/$DIR.txz
else
sudo apt update -qq
sudo apt install -y libcap-dev
URL=https://github.com/$REPO/releases/download/latest/$TOOL.tar.xz
fi
mkdir -p $HOME/tools
URL=https://github.com/$REPO/releases/download/latest/$DIR.tar.xz
[ "$ARCH" = lexra ] && URL=https://github.com/$REPO_LEXRA/raw/refs/heads/master/$DIR.txz
wget -qO- $URL | tar -C $HOME/tools -xJ || exit 1
[ -d "$HOME/tools/$DIR/bin" ] && echo "$HOME/tools/$DIR/bin" >> $GITHUB_PATH
[[ -d "$HOME/tools/$DIR/bin" ]] && echo "$HOME/tools/$DIR/bin" >> $GITHUB_PATH
- name: Build
env:
ARCH: ${{ matrix.arch }}
TARGET: ${{ matrix.tool }}
CFLAGS: ${{ matrix.env.CFLAGS != '' && matrix.env.CFLAGS || null }}
LDFLAGS: ${{ matrix.env.LDFLAGS != '' && matrix.env.LDFLAGS || null }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
DEPS_DIR=$GITHUB_WORKSPACE/deps
@@ -93,10 +101,7 @@ jobs:
export NM=$TARGET-nm
export STRIP=$TARGET-strip
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
export STAGING_DIR=/tmp
LDFLAGS=
[ "$ARCH" = lexra ] && LDFLAGS=-lgcc_eh
export LDFLAGS
export STAGING_DIR=$RUNNER_TEMP
# netfilter libs
wget -qO- https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj
@@ -106,7 +111,7 @@ jobs:
for i in libmnl libnfnetlink libnetfilter_queue ; do
(
cd $i-*
CFLAGS="-Os -flto=auto" \
CFLAGS="-Os -flto=auto $CFLAGS" \
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
make install -j$(nproc) DESTDIR=$DEPS_DIR
)
@@ -118,7 +123,7 @@ jobs:
xargs -I{} wget -qO- https://github.com/madler/zlib/archive/refs/tags/{}.tar.gz | tar -xz
(
cd zlib-*
CFLAGS="-Os -flto=auto" \
CFLAGS="-Os -flto=auto $CFLAGS" \
./configure --prefix= --static
make install -j$(nproc) DESTDIR=$DEPS_DIR
)
@@ -129,7 +134,7 @@ jobs:
install -Dm644 -t $DEPS_DIR/include/sys /usr/include/x86_64-linux-gnu/sys/queue.h /usr/include/sys/capability.h
# zapret
CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }} -static-libgcc -static -I$DEPS_DIR/include" \
CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }} -static-libgcc -static -I$DEPS_DIR/include $CFLAGS" \
LDFLAGS="-L$DEPS_DIR/lib $LDFLAGS" \
make -C zapret -j$(nproc)
tar -C zapret/binaries/my -cJf zapret-linux-$ARCH.tar.xz .
@@ -322,11 +327,12 @@ jobs:
- name: Build
env:
ABI: ${{ matrix.abi }}
API: 21
TARGET: ${{ matrix.target }}
GH_TOKEN: ${{ github.token }}
run: |
DEPS_DIR=$GITHUB_WORKSPACE/deps
export TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64
export API=21
export CC="$TOOLCHAIN/bin/clang --target=$TARGET$API"
export AR=$TOOLCHAIN/bin/llvm-ar
export AS=$CC
@@ -355,6 +361,12 @@ jobs:
CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }} -I$DEPS_DIR/include" \
LDFLAGS="-L$DEPS_DIR/lib" \
make -C zapret android -j$(nproc)
# strip unwanted ELF sections to prevent warnings on old Android versions
gh api repos/termux/termux-elf-cleaner/releases/latest --jq '.tag_name' |\
xargs -I{} wget -O elf-cleaner https://github.com/termux/termux-elf-cleaner/releases/download/{}/termux-elf-cleaner
chmod +x elf-cleaner
./elf-cleaner --api-level $API zapret/binaries/my/*
zip zapret-android-$ABI.zip -j zapret/binaries/my/*
- name: Upload artifacts
@@ -389,6 +401,7 @@ jobs:
uses: crazy-max/ghaction-upx@v3
with:
install-only: true
version: v4.2.4
- name: Prepare binaries
shell: bash
@@ -414,7 +427,6 @@ jobs:
unzip $f -d $dir && rm $f
if [[ $dir =~ win ]]; then
chmod -x $dir/*
run_upx --force $dir/cygwin1.dll
fi
;;
esac
@@ -425,23 +437,23 @@ jobs:
if [ -d $dir ]; then
echo "Processing $dir"
case $dir in
*-android-arm64-v8a ) run_dir android-aarch64 ;;
*-android-arm64-v8a ) run_dir android-arm64 ;;
*-android-armeabi-v7a ) run_dir android-arm ;;
*-android-x86 ) run_dir android-x86 ;;
*-android-x86_64 ) run_dir android-x86_64 ;;
*-freebsd-x86_64 ) run_dir freebsd-x64 ;;
*-linux-arm ) run_dir arm ;;
*-linux-arm64 ) run_dir aarch64 ;;
*-linux-mips64 ) run_dir mips64r2-msb ;;
*-linux-mipselsf ) run_dir mips32r1-lsb ;;
*-linux-mipssf ) run_dir mips32r1-msb ;;
*-linux-ppc ) run_dir ppc ;;
*-linux-x86 ) run_dir x86 ;;
*-linux-x86_64 ) run_dir x86_64 ;;
*-linux-lexra ) run_dir lexra ;;
*-freebsd-x86_64 ) run_dir freebsd-x86_64 ;;
*-linux-arm ) run_dir linux-arm ;;
*-linux-arm64 ) run_dir linux-arm64 ;;
*-linux-mips64 ) run_dir linux-mips64 ;;
*-linux-mipselsf ) run_dir linux-mipsel ;;
*-linux-mipssf ) run_dir linux-mips ;;
*-linux-ppc ) run_dir linux-ppc ;;
*-linux-x86 ) run_dir linux-x86 ;;
*-linux-x86_64 ) run_dir linux-x86_64 ;;
*-linux-lexra ) run_dir linux-lexra ;;
*-mac-x64 ) run_dir mac64 ;;
*-win-x86 ) run_dir win32 ;;
*-win-x86_64 ) run_dir win64 ;;
*-win-x86 ) run_dir windows-x86 ;;
*-win-x86_64 ) run_dir windows-x86_64 ;;
esac
fi
done
@@ -456,7 +468,7 @@ jobs:
(
cd ${{ env.repo_dir }}
rm -rf binaries/{android*,freebsd*,mac*,win*,x86_64/tpws_wsl.tgz} \
init.d/{openrc,macos,pfsense,runit,s6,systemd} \
init.d/{openrc,macos,pfsense,runit,s6,systemd,windivert.filter.examples} \
tpws nfq ip2net mdig docs files/huawei Makefile
)
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }}

2
.gitignore vendored
View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -4,6 +4,10 @@ which()
# 'command -v' replacement does not work exactly the same way. it outputs shell aliases if present
# $1 - executable name
local IFS=:
[ "$1" != "${1#/}" ] && [ -x "$1" ] && {
echo "$1"
return 0
}
for p in $PATH; do
[ -x "$p/$1" ] && {
echo "$p/$1"
@@ -93,6 +97,18 @@ trim()
{
awk '{gsub(/^ +| +$/,"")}1'
}
split_by_separator()
{
# $1 - string
# $2 - separator
# $3 - var name to get "before" part
# $4 - var name to get "after" part
local before="${1%%$2*}"
local after="${1#*$2}"
[ "$after" = "$1" ] && after=
[ -n "$3" ] && eval $3="\$before"
[ -n "$4" ] && eval $4="\$after"
}
dir_is_not_empty()
{
@@ -241,7 +257,7 @@ fix_sbin_path()
# it can calculate floating point expr
calc()
{
awk "BEGIN { print $*}";
LC_ALL=C awk "BEGIN { print $*}";
}
fsleep_setup()
@@ -297,10 +313,10 @@ minsleep()
replace_char()
{
local a=$1
local b=$2
local a="$1"
local b="$2"
shift; shift
echo "$@" | tr $a $b
echo "$@" | tr "$a" "$b"
}
replace_str()
@@ -318,18 +334,32 @@ setup_md5()
exists $MD5 || MD5=md5
}
md5f()
{
setup_md5
$MD5 | cut -d ' ' -f1
}
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 | md5f | sed 's/[^0-9]//g' | $RCUT)
echo $(( ($r % ($2-$1+1)) + $1 ))
}
@@ -396,14 +426,17 @@ std_ports()
has_bad_ws_options()
{
# $1 - nfqws/tpws opts
# ПРИМЕЧАНИЕ ДЛЯ РАСПРОСТРАНИТЕЛЕЙ КОПИПАСТЫ
# ЭТОТ КОД СДЕЛАН СПЕЦИАЛЬНО ДЛЯ ВАС, ЧТОБЫ ВЫ НЕ ПОСТИЛИ В СЕТЬ ПЛОХИЕ РЕЦЕПТЫ
# ЕСЛИ ВАМ ХОЧЕТСЯ ЕГО УДАЛИТЬ И НАПИСАТЬ ИНСТРУКЦИЮ КАК ЕГО УДАЛЯТЬ, ВЫ ДЕЛАЕТЕ ХРЕНОВУЮ УСЛУГУ. НАПИШИТЕ ЛУЧШЕ custom script.
# custom script - ЭТО ФАЙЛИК, КОТОРЫЙ ДОСТАТОЧНО СКОПИРОВАТЬ В НУЖНУЮ ДИРЕКТОРИЮ, ЧТОБЫ ОН СДЕЛАЛ ТОЖЕ САМОЕ, НО ЭФФЕКТИВНО.
# ФИЛЬТРАЦИЯ ПО IPSET В ЯДРЕ НЕСРАВНИМО ЭФФЕКТИВНЕЕ, ЧЕМ ПЕРЕКИДЫВАТЬ ВСЕ ПАКЕТЫ В nfqws И ТАМ ФИЛЬТРОВАТЬ
# --ipset СУЩЕСТВУЕТ ТОЛЬКО ДЛЯ ВИНДЫ И LINUX СИСТЕМ БЕЗ ipset (НАПРИМЕР, Android).
# И ТОЛЬКО ПО ЭТОЙ ПРИЧИНЕ ОНО НЕ ВЫКИНУТО ПОЛНОСТЬЮ ИЗ LINUX ВЕРСИИ
contains "$1" "--ipset"
contains "$1" "--ipset" && {
echo
echo "WARNING !!! --ipset parameter is present"
echo "It's OK if you only specialize already redirected traffic and also process the rest."
echo "If you redirect port X to process several IPs from the list and do nothing with the rest - IT'S VERY INEFFECTIVE !"
echo "Kernel ipsets should be used instead. Write custom scripts and filter IPs in kernel."
echo
}
return 1
}
check_bad_ws_options()
{
@@ -419,8 +452,5 @@ check_bad_ws_options()
}
help_bad_ws_options()
{
echo "WARNING ! you have specified --ipset option"
echo "WARNING ! it would work but on ${UNAME:-$(uname)} it's not the best option"
echo "WARNING ! you should use kernel mode sets. they are much more efficient."
echo "WARNING ! to use ipsets you have to write your own custom script"
echo "WARNING ! BAD options detected"
}

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
@@ -187,7 +187,7 @@ check_system()
SYSTEM=
SUBSYS=
SYSTEMCTL=$(whichq systemctl)
SYSTEMCTL="$(whichq systemctl)"
get_fwtype
OPENWRT_FW3=
@@ -203,6 +203,7 @@ check_system()
# some distros include systemctl without systemd
if [ -d "$SYSTEMD_DIR" ] && [ -x "$SYSTEMCTL" ] && [ "$INIT" = "systemd" ]; then
SYSTEM=systemd
[ -f "$EXEDIR/init.d/sysv/functions" ] && . "$EXEDIR/init.d/sysv/functions"
elif [ -f "/etc/openwrt_release" ] && exists opkg || exists apk && exists uci && [ "$INIT" = "procd" ] ; then
SYSTEM=openwrt
OPENWRT_PACKAGER=opkg
@@ -226,8 +227,10 @@ check_system()
OPENWRT_FW4=1
info="${info}firewall fw4. flow offloading requires nftables."
fi
[ -f "$EXEDIR/init.d/openwrt/functions" ] && . "$EXEDIR/init.d/openwrt/functions"
elif openrc_test; then
SYSTEM=openrc
[ -f "$EXEDIR/init.d/sysv/functions" ] && . "$EXEDIR/init.d/sysv/functions"
else
echo system is not either systemd, openrc or openwrt based
echo easy installer can set up config settings but can\'t configure auto start
@@ -237,10 +240,12 @@ check_system()
else
exitp 5
fi
[ -f "$EXEDIR/init.d/sysv/functions" ] && . "$EXEDIR/init.d/sysv/functions"
fi
linux_get_subsys
elif [ "$UNAME" = "Darwin" ]; then
SYSTEM=macos
[ -f "$EXEDIR/init.d/macos/functions" ] && . "$EXEDIR/init.d/macos/functions"
else
echo easy installer only supports Linux and MacOS. check readme.md for supported systems and manual setup info.
exitp 5
@@ -617,11 +622,17 @@ write_config_var()
replace_var_def $1 "$M" "$ZAPRET_CONFIG"
}
no_prereq_exit()
{
echo could not install prerequisites
exitp 6
}
check_prerequisites_linux()
{
echo \* checking prerequisites
local s cmd PKGS UTILS req="curl curl"
local APTGET DNF YUM PACMAN ZYPPER EOPKG APK
case "$FWTYPE" in
iptables)
req="$req iptables iptables ip6tables iptables ipset ipset"
@@ -650,6 +661,7 @@ check_prerequisites_linux()
echo packages required : $PKGS
APTGET=$(whichq apt-get)
DNF=$(whichq dnf)
YUM=$(whichq yum)
PACMAN=$(whichq pacman)
ZYPPER=$(whichq zypper)
@@ -657,39 +669,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
@@ -707,7 +703,7 @@ removable_pkgs_openwrt()
for pkg in $PKGS2; do
check_package_exists_openwrt $pkg && PKGS="${PKGS:+$PKGS }$pkg"
done
PKGS="ipset iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra ip6tables-mod-nat ip6tables-extra kmod-nft-queue gzip coreutils-sort coreutils-sleep curl $PKGS"
PKGS="ipset iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra iptables-mod-u32 ip6tables-mod-nat ip6tables-extra kmod-nft-queue gzip coreutils-sort coreutils-sleep curl $PKGS"
}
openwrt_fix_broken_apk_uninstall_scripts()
@@ -748,7 +744,7 @@ check_prerequisites_openwrt()
iptables)
pkg_iptables=iptables
check_package_exists_openwrt iptables-zz-legacy && pkg_iptables=iptables-zz-legacy
PKGS="$PKGS ipset $pkg_iptables iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra"
PKGS="$PKGS ipset $pkg_iptables iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra iptables-mod-u32"
check_package_exists_openwrt ip6tables-zz-legacy && pkg_iptables=ip6tables-zz-legacy
[ "$DISABLE_IPV6" = 1 ] || PKGS="$PKGS $pkg_iptables ip6tables-mod-nat ip6tables-extra"
;;
@@ -843,13 +839,13 @@ dry_run_tpws_()
{
local TPWS="$ZAPRET_BASE/tpws/tpws"
echo verifying tpws options
"$TPWS" --dry-run "$@"
"$TPWS" --dry-run ${WS_USER:+--user=$WS_USER} "$@"
}
dry_run_nfqws_()
{
local NFQWS="$ZAPRET_BASE/nfq/nfqws"
echo verifying nfqws options
"$NFQWS" --dry-run "$@"
"$NFQWS" --dry-run ${WS_USER:+--user=$WS_USER} "$@"
}
dry_run_tpws()
{

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()
{
@@ -108,6 +112,10 @@ unprepare_tpws_fw()
unprepare_tpws_fw4
}
ipt_mark_filter()
{
[ -n "$FILTER_MARK" ] && echo "-m mark --mark $FILTER_MARK/$FILTER_MARK"
}
ipt_print_op()
{
@@ -132,7 +140,7 @@ _fw_tpws4()
ipt_print_op $1 "$2" "tpws (port $3)"
rule="$2 $IPSET_EXCLUDE dst -j DNAT --to $TPWS_LOCALHOST4:$3"
rule="$(ipt_mark_filter) $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 +168,7 @@ _fw_tpws6()
ipt_print_op $1 "$2" "tpws (port $3)" 6
rule="$2 $IPSET_EXCLUDE6 dst"
rule="$(ipt_mark_filter) $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
@@ -198,7 +206,7 @@ _fw_nfqws_post4()
ipt_print_op $1 "$2" "nfqws postrouting (qnum $3)"
rule="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK $2 $IPSET_EXCLUDE dst -j NFQUEUE --queue-num $3 --queue-bypass"
rule="$(ipt_mark_filter) -m mark ! --mark $DESYNC_MARK/$DESYNC_MARK $2 $IPSET_EXCLUDE dst -j NFQUEUE --queue-num $3 --queue-bypass"
if [ -n "$4" ] ; then
for i in $4; do
ipt_add_del $1 POSTROUTING -t mangle -o $i $rule
@@ -219,7 +227,7 @@ _fw_nfqws_post6()
ipt_print_op $1 "$2" "nfqws postrouting (qnum $3)" 6
rule="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK $2 $IPSET_EXCLUDE6 dst -j NFQUEUE --queue-num $3 --queue-bypass"
rule="$(ipt_mark_filter) -m mark ! --mark $DESYNC_MARK/$DESYNC_MARK $2 $IPSET_EXCLUDE6 dst -j NFQUEUE --queue-num $3 --queue-bypass"
if [ -n "$4" ] ; then
for i in $4; do
ipt6_add_del $1 POSTROUTING -t mangle -o $i $rule
@@ -387,6 +395,27 @@ zapret_do_firewall_rules_ipt()
zapret_do_firewall_standard_rules_ipt $1
custom_runner zapret_custom_firewall $1
zapret_do_icmp_filter $1
}
zapret_do_icmp_filter()
{
# $1 - 1 - add, 0 - del
local FW_EXTRA_PRE= FW_EXTRA_POST=
[ "$FILTER_TTL_EXPIRED_ICMP" = 1 ] && {
[ "$DISABLE_IPV4" = 1 ] || {
ipt_add_del $1 POSTROUTING -t mangle -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j CONNMARK --or-mark $DESYNC_MARK
ipt_add_del $1 INPUT -p icmp -m icmp --icmp-type time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
ipt_add_del $1 FORWARD -p icmp -m icmp --icmp-type time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
}
[ "$DISABLE_IPV6" = 1 ] || {
ipt6_add_del $1 POSTROUTING -t mangle -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j CONNMARK --or-mark $DESYNC_MARK
ipt6_add_del $1 INPUT -p icmpv6 -m icmp6 --icmpv6-type time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
ipt6_add_del $1 FORWARD -p icmpv6 -m icmp6 --icmpv6-type time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
}
}
}
zapret_do_firewall_ipt()

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()
{
@@ -109,6 +111,14 @@ unprepare_route_localnet()
set_route_localnet 0 "$@"
}
get_uevent_devtype()
{
local DEVTYPE INTERFACE IFINDEX OF_NAME OF_FULLNAME OF_COMPATIBLE_N
[ -f "/sys/class/net/$1/uevent" ] && {
. "/sys/class/net/$1/uevent"
echo -n $DEVTYPE
}
}
resolve_lower_devices()
{
# $1 - bridge interface name

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
@@ -106,7 +106,7 @@ cat << EOF | nft -f -
flush chain inet $ZAPRET_NFT_TABLE predefrag_nfqws
add rule inet $ZAPRET_NFT_TABLE predefrag mark and $DESYNC_MARK !=0 jump predefrag_nfqws comment "nfqws generated : avoid drop by INVALID conntrack state"
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws mark and $DESYNC_MARK_POSTNAT !=0 notrack comment "postnat traffic"
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws ip frag-off != 0 notrack comment "ipfrag"
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws ip frag-off & 0x1fff != 0 notrack comment "ipfrag"
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws exthdr frag exists notrack comment "ipfrag"
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws tcp flags ! syn,rst,ack notrack comment "datanoack"
add set inet $ZAPRET_NFT_TABLE lanif { type ifname; }
@@ -119,6 +119,20 @@ EOF
nft_flush_chain predefrag_nfqws
nft_add_rule predefrag_nfqws notrack comment \"do not track nfqws generated packets to avoid nat tampering and defragmentation\"
}
[ "$FILTER_TTL_EXPIRED_ICMP" = 1 ] && {
if is_postnat; then
# can be caused by untracked nfqws-generated packets
nft_add_rule prerouting icmp type time-exceeded ct state invalid drop
else
nft_add_rule postrouting_hook mark and $DESYNC_MARK != 0 ct mark set ct mark or $DESYNC_MARK comment \"nfqws related : prevent ttl expired socket errors\"
fi
[ "$DISABLE_IPV4" = "1" ] || {
nft_add_rule prerouting icmp type time-exceeded ct mark and $DESYNC_MARK != 0 drop comment \"nfqws related : prevent ttl expired socket errors\"
}
[ "$DISABLE_IPV6" = "1" ] || {
nft_add_rule prerouting icmpv6 type time-exceeded ct mark and $DESYNC_MARK != 0 drop comment \"nfqws related : prevent ttl expired socket errors\"
}
}
}
nft_del_chains()
{
@@ -263,28 +277,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
@@ -320,6 +312,10 @@ nft_filter_apply_ipset_target()
nft_filter_apply_ipset_target6 $2
}
nft_mark_filter()
{
[ -n "$FILTER_MARK" ] && echo "mark and $FILTER_MARK != 0"
}
nft_script_add_ifset_element()
{
@@ -342,7 +338,7 @@ nft_fill_ifsets()
# $5 - space separated wan physical interface names (optional)
# $6 - space separated wan6 physical interface names (optional)
local script i j ALLDEVS devs
local script i j ALLDEVS devs b
# if large sets exist nft works very ineffectively
# looks like it analyzes the whole table blob to find required data pieces
@@ -370,17 +366,18 @@ 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
# 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
b=
devs=$(resolve_lower_devices $i)
for j in $devs; do
# do not display error if addition failed
nft_create_or_update_flowtable 'offload' $j && b=1 2>/dev/null
done
[ -n "$b" ] || {
# no lower devices added ? try to add interface itself
nft_create_or_update_flowtable 'offload' $i 2>/dev/null
}
done
;;
esac
@@ -410,9 +407,10 @@ _nft_fw_tpws4()
[ "$DISABLE_IPV4" = "1" -o -z "$1" ] || {
local filter="$1" port="$2"
local mark_filter=$(nft_mark_filter)
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} $mark_filter $filter ip daddr != @nozapret ip daddr != @ipban $FW_EXTRA_POST dnat ip to $TPWS_LOCALHOST4:$port
nft_insert_rule dnat_pre iifname @lanif $mark_filter $filter ip daddr != @nozapret ip daddr != @ipban $FW_EXTRA_POST dnat ip to $TPWS_LOCALHOST4:$port
prepare_route_localnet
}
}
@@ -425,10 +423,11 @@ _nft_fw_tpws6()
[ "$DISABLE_IPV6" = "1" -o -z "$1" ] || {
local filter="$1" port="$2" DNAT6 i
local mark_filter=$(nft_mark_filter)
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} $mark_filter $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 $mark_filter $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
@@ -475,9 +474,9 @@ _nft_fw_nfqws_post4()
[ "$DISABLE_IPV4" = "1" -o -z "$1" ] || {
local filter="$1" port="$2" rule chain=$(get_postchain) setmark
nft_print_op "$filter" "nfqws postrouting (qnum $port)" 4
rule="${3:+oifname @wanif }$filter ip daddr != @nozapret"
rule="${3:+oifname @wanif} $(nft_mark_filter) $filter ip daddr != @nozapret"
is_postnat && setmark="meta mark set meta mark or $DESYNC_MARK_POSTNAT"
nft_insert_rule $chain $rule $setmark $FW_EXTRA_POST queue num $port bypass
nft_insert_rule $chain $rule $setmark $CONNMARKER $FW_EXTRA_POST queue num $port bypass
nft_add_nfqws_flow_exempt_rule "$rule"
}
}
@@ -490,9 +489,9 @@ _nft_fw_nfqws_post6()
[ "$DISABLE_IPV6" = "1" -o -z "$1" ] || {
local filter="$1" port="$2" rule chain=$(get_postchain) setmark
nft_print_op "$filter" "nfqws postrouting (qnum $port)" 6
rule="${3:+oifname @wanif6 }$filter ip6 daddr != @nozapret6"
rule="${3:+oifname @wanif6} $(nft_mark_filter) $filter ip6 daddr != @nozapret6"
is_postnat && setmark="meta mark set meta mark or $DESYNC_MARK_POSTNAT"
nft_insert_rule $chain $rule $setmark $FW_EXTRA_POST queue num $port bypass
nft_insert_rule $chain $rule $setmark $CONNMARKER $FW_EXTRA_POST queue num $port bypass
nft_add_nfqws_flow_exempt_rule "$rule"
}
}
@@ -515,8 +514,8 @@ _nft_fw_nfqws_pre4()
[ "$DISABLE_IPV4" = "1" -o -z "$1" ] || {
local filter="$1" port="$2" rule
nft_print_op "$filter" "nfqws prerouting (qnum $port)" 4
rule="${3:+iifname @wanif }$filter ip saddr != @nozapret"
nft_insert_rule $(get_prechain) $rule $FW_EXTRA_POST queue num $port bypass
rule="${3:+iifname @wanif} $filter ip saddr != @nozapret"
nft_insert_rule $(get_prechain) $rule $CONNMARKER $FW_EXTRA_POST queue num $port bypass
}
}
_nft_fw_nfqws_pre6()
@@ -528,8 +527,8 @@ _nft_fw_nfqws_pre6()
[ "$DISABLE_IPV6" = "1" -o -z "$1" ] || {
local filter="$1" port="$2" rule
nft_print_op "$filter" "nfqws prerouting (qnum $port)" 6
rule="${3:+iifname @wanif6 }$filter ip6 saddr != @nozapret6"
nft_insert_rule $(get_prechain) $rule $FW_EXTRA_POST queue num $port bypass
rule="${3:+iifname @wanif6} $filter ip6 saddr != @nozapret6"
nft_insert_rule $(get_prechain) $rule $CONNMARKER $FW_EXTRA_POST queue num $port bypass
}
}
nft_fw_nfqws_pre()
@@ -707,3 +706,7 @@ zapret_do_firewall_nft()
return 0
}
# ctmark is not available in POSTNAT mode
CONNMARKER=
[ "$FILTER_TTL_EXPIRED_ICMP" = 1 ] && is_postnat && CONNMARKER="ct mark set ct mark or $DESYNC_MARK"

View File

@@ -1,85 +0,0 @@
apply_unspecified_desync_modes()
{
NFQWS_OPT_DESYNC_HTTP="${NFQWS_OPT_DESYNC_HTTP:-$NFQWS_OPT_DESYNC}"
NFQWS_OPT_DESYNC_HTTP_SUFFIX="${NFQWS_OPT_DESYNC_HTTP_SUFFIX:-$NFQWS_OPT_DESYNC_SUFFIX}"
NFQWS_OPT_DESYNC_HTTPS="${NFQWS_OPT_DESYNC_HTTPS:-$NFQWS_OPT_DESYNC}"
NFQWS_OPT_DESYNC_HTTPS_SUFFIX="${NFQWS_OPT_DESYNC_HTTPS_SUFFIX:-$NFQWS_OPT_DESYNC_SUFFIX}"
NFQWS_OPT_DESYNC_HTTP6="${NFQWS_OPT_DESYNC_HTTP6:-$NFQWS_OPT_DESYNC_HTTP}"
NFQWS_OPT_DESYNC_HTTP6_SUFFIX="${NFQWS_OPT_DESYNC_HTTP6_SUFFIX:-$NFQWS_OPT_DESYNC_HTTP_SUFFIX}"
NFQWS_OPT_DESYNC_HTTPS6="${NFQWS_OPT_DESYNC_HTTPS6:-$NFQWS_OPT_DESYNC_HTTPS}"
NFQWS_OPT_DESYNC_HTTPS6_SUFFIX="${NFQWS_OPT_DESYNC_HTTPS6_SUFFIX:-$NFQWS_OPT_DESYNC_HTTPS_SUFFIX}"
NFQWS_OPT_DESYNC_QUIC6="${NFQWS_OPT_DESYNC_QUIC6:-$NFQWS_OPT_DESYNC_QUIC}"
NFQWS_OPT_DESYNC_QUIC6_SUFFIX="${NFQWS_OPT_DESYNC_QUIC6_SUFFIX:-$NFQWS_OPT_DESYNC_QUIC_SUFFIX}"
}
get_nfqws_qnums()
{
# $1 - var name for ipv4 http
# $2 - var name for ipv4 https
# $3 - var name for ipv6 http
# $4 - var name for ipv6 https
local _qn _qns _qn6 _qns6
[ "$DISABLE_IPV4" = "1" ] || {
_qn=$QNUM
_qns=$_qn
[ "$NFQWS_OPT_DESYNC_HTTP $NFQWS_OPT_DESYNC_HTTP_SUFFIX" = "$NFQWS_OPT_DESYNC_HTTPS $NFQWS_OPT_DESYNC_HTTPS_SUFFIX" ] || _qns=$(($QNUM+1))
}
[ "$DISABLE_IPV6" = "1" ] || {
_qn6=$(($QNUM+2))
_qns6=$(($QNUM+3))
[ "$DISABLE_IPV4" = "1" ] || {
if [ "$NFQWS_OPT_DESYNC_HTTP6 $NFQWS_OPT_DESYNC_HTTP6_SUFFIX" = "$NFQWS_OPT_DESYNC_HTTP $NFQWS_OPT_DESYNC_HTTP_SUFFIX" ]; then
_qn6=$_qn;
elif [ "$NFQWS_OPT_DESYNC_HTTP6 $NFQWS_OPT_DESYNC_HTTP6_SUFFIX" = "$NFQWS_OPT_DESYNC_HTTPS $NFQWS_OPT_DESYNC_HTTPS_SUFFIX" ]; then
_qn6=$_qns;
fi
if [ "$NFQWS_OPT_DESYNC_HTTPS6 $NFQWS_OPT_DESYNC_HTTPS6_SUFFIX" = "$NFQWS_OPT_DESYNC_HTTP $NFQWS_OPT_DESYNC_HTTP_SUFFIX" ]; then
_qns6=$_qn;
elif [ "$NFQWS_OPT_DESYNC_HTTPS6 $NFQWS_OPT_DESYNC_HTTPS6_SUFFIX" = "$NFQWS_OPT_DESYNC_HTTPS $NFQWS_OPT_DESYNC_HTTPS_SUFFIX" ]; then
_qns6=$_qns;
fi
}
[ "$NFQWS_OPT_DESYNC_HTTPS6 $NFQWS_OPT_DESYNC_HTTPS6_SUFFIX" = "$NFQWS_OPT_DESYNC_HTTP6 $NFQWS_OPT_DESYNC_HTTP6_SUFFIX" ] && _qns6=$_qn6;
}
if [ "$MODE_HTTP" = 1 ]; then
eval $1=$_qn
eval $3=$_qn6
else
eval $1=
eval $3=
fi
if [ "$MODE_HTTPS" = 1 ]; then
eval $2=$_qns
eval $4=$_qns6
else
eval $2=
eval $4=
fi
}
get_nfqws_qnums_quic()
{
# $1 - var name for ipv4 quic
# $2 - var name for ipv6 quic
local _qn _qn6
[ "$DISABLE_IPV4" = "1" ] || {
_qn=$(($QNUM+10))
}
[ "$DISABLE_IPV6" = "1" ] || {
_qn6=$(($QNUM+11))
[ "$DISABLE_IPV4" = "1" ] || {
if [ "$NFQWS_OPT_DESYNC_QUIC $NFQWS_OPT_DESYNC_QUIC_SUFFIX" = "$NFQWS_OPT_DESYNC_QUIC6 $NFQWS_OPT_DESYNC_QUIC6_SUFFIX" ]; then
_qn6=$_qn;
fi
}
}
if [ "$MODE_QUIC" = 1 ]; then
eval $1=$_qn
eval $2=$_qn6
else
eval $1=
eval $2=
fi
}

View File

@@ -47,6 +47,12 @@ GZIP_LISTS=1
DESYNC_MARK=0x40000000
DESYNC_MARK_POSTNAT=0x20000000
# do not pass outgoing traffic to tpws/nfqws not marked with this bit
# this setting allows to write your own rules to limit traffic that should be fooled
# for example based on source IP or incoming interface name
# no filter if not defined
#FILTER_MARK=0x10000000
TPWS_SOCKS_ENABLE=0
# tpws socks listens on this port on localhost and LAN interfaces
TPPORT_SOCKS=987
@@ -97,7 +103,7 @@ NFQWS_OPT="
# none,ipset,hostlist,autohostlist
MODE_FILTER=none
# openwrt only : donttouch,none,software,hardware
# donttouch,none,software,hardware
FLOWOFFLOAD=donttouch
# openwrt: specify networks to be treated as LAN. default is "lan"
@@ -129,6 +135,11 @@ INIT_APPLY_FW=1
# do not work with ipv6
DISABLE_IPV6=1
# drop icmp time exceeded messages for nfqws tampered connections
# in POSTNAT mode this can interfere with default mtr/traceroute in tcp or udp mode. use source port not redirected to nfqws
# set to 0 if you are not expecting connection breakage due to icmp in response to TCP SYN or UDP
FILTER_TTL_EXPIRED_ICMP=1
# select which init script will be used to get ip or host list
# possible values : get_user.sh get_antizapret.sh get_combined.sh get_reestr.sh get_hostlist.sh
# comment if not required

View File

@@ -312,7 +312,7 @@ In OpenBSD default `tpws` bind is ipv6 only. To bind to ipv4 specify
Use `--bind-addr=0.0.0.0 --bind-addr=::` to achieve the same default bind as in
others OSes.
`tpws` for forwarded traffic only :
`tpws` for forwarded traffic only (OLDER OS versions):
`/etc/pf.conf`:
```
@@ -323,13 +323,31 @@ pass in quick on em1 inet6 proto tcp to port {80,443} rdr-to ::1 port 988
Then:
```
pfctl -f /etc/pf.conf
tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1
tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1 --enable-pf
```
Its not clear how to do rdr-to outgoing traffic. I could not make route-to
scheme work. rdr-to support is done using /dev/pf, that's why transparent mode
requires root.
`tpws` for forwarded traffic only (NEWER OS versions):
```
pass on em1 inet proto tcp to port {80,443} divert-to 127.0.0.1 port 989
pass on em1 inet6 proto tcp to port {80,443} divert-to ::1 port 989
```
Then:
```
pfctl -f /etc/pf.conf
tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1
```
tpws must be bound exactly to diverted IPs, not `0.0.0.0` or `::`.
It's also not clear how to divert connections from local system.
`dvtws` for all traffic:
`/etc/pf.conf`:

View File

@@ -19,7 +19,8 @@
* [pfsense](#pfsense)
* [OpenBSD](#openbsd)
* [tpws bind на ipv4](#tpws-bind-на-ipv4)
* [tpws для проходящего трафика](#tpws-для-проходящего-трафика)
* [tpws для проходящего трафика (старые системы)](#tpws-для-проходящего-трафика-старая-схема-не-работает-в-новых-версиях))
* [tpws для проходящего трафика (новые системы)](#tpws-для-проходящего-трафика-новые-системы))
* [Запуск dvtws](#запуск-dvtws)
* [Проблемы с badsum](#проблемы-с-badsum)
* [Особенность отправки fake пакетов](#особенность-отправки-fake-пакетов)
@@ -392,7 +393,11 @@ rdr pass on em1 inet6 proto tcp from any to any port = https -> fe80::20c:29ff:5
Но лучше все же так не делать, а сажать на определенные внутренние адреса или интерфейсы.
### tpws для проходящего трафика
### tpws для проходящего трафика (старая схема не работает в новых версиях)
В этом варианте tpws обращается явно к редиректору pf и пытается от него получить оригинальный адрес назначения.
Как показывает практика, это не работает на новых версиях OpenBSD. Возвращается ошибка ioctl.
Последняя проверенная версия, где это работает, - 6.8 . Между 6.8 и 7.4 разработчики сломали этот механизм.
`/etc/pf.conf`:
```
@@ -402,15 +407,35 @@ pass in quick on em1 inet6 proto tcp to port {80,443} rdr-to ::1 port 988
```sh
$ pfctl -f /etc/pf.conf
$ tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1
$ tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1 --enable-pf
```
> [!NOTE]
> [!NOTE]
> В PF не выходит делать rdr-to с той же системы, где работает proxy.
> Вариант с route-to не сохраняет мета информацию. Адрес назначения теряется.
> Поэтому этот вариант годится для squid, берущего адрес из протокола прикладного уровня, но не годится для tpws, полагающегося на метаданные ОС.
> Поддержка rdr-to реализована через `/dev/pf`, поэтому прозрачный режим **требует root**.
### tpws для проходящего трафика (новые системы)
В новых версиях предлагается использовать divert-to вместо rdr-to.
Минимально проверенная версия, где это работает, 7.4. Может работать или не работать на более старых - исследование не проводилось.
`/etc/pf.conf`:
```
pass on em1 inet proto tcp to port {80,443} divert-to 127.0.0.1 port 989
pass on em1 inet6 proto tcp to port {80,443} divert-to ::1 port 989
```
tpws должен иметь бинд на точно такой адрес, который указан в правилах pf. `0.0.0.0` или `::` не работает.
```sh
$ pfctl -f /etc/pf.conf
$ tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1
```
> [!NOTE]
> Так же не понятно как делать divert с самой системы, где работает tpws.
### Запуск dvtws

View File

@@ -56,14 +56,27 @@ sysctl net.inet6.ip6.forwarding=1
OpenBSD PF :
(OLD OpenBSD versions)
; dont know how to rdr-to from local system. doesn't seem to work. only works for routed traffic.
/etc/pf.conf
pass in quick on em1 inet proto tcp to port {80,443} rdr-to 127.0.0.1 port 988
pass in quick on em1 inet6 proto tcp to port {80,443} rdr-to ::1 port 988
pfctl -f /etc/pf.conf
/opt/zapret/tpws/tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1 --enable-pf
(NEW OpenBSD versions)
; dont know how to divert-to from local system
/etc/pf.conf
pass on em1 inet proto tcp to port {80,443} divert-to 127.0.0.1 port 989
pass on em1 inet6 proto tcp to port {80,443} divert-to ::1 port 989
pfctl -f /etc/pf.conf
/opt/zapret/tpws/tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1
; dvtws works both for routed and local
pass in quick on em0 proto tcp from port {80,443} flags SA/SA divert-packet port 989 no state

View File

@@ -434,3 +434,145 @@ v69.8
winws: accept empty outgoing RST and FIN packets for conntrack needs
repo: lexra build
v69.9
init.d: exclude ipban from tpws redirection
macos: fix install_easy
macos: fix national decimal separator in sleep
ipset: scripts maintenance
v70
blockcheck: override all dialog questions and enable batch mode
blockcheck: parallel attempts
nfqws: weaken wireguard initiation recognition. use len=148 and data[0]=1 signature
nfqws: apply split+seqovl only to the first reasm fragment
install_easy: dnf packager support
nfqws,tpws: hostlist/ipset track not only file mod time but also file size
nfqws,tpws,ipset: return lists reload on HUP
nfqws,blockcheck: --dpi-desync-fake-tls-mod
v70.1
nfqws: --dpi-desync-fake-tls-mod=dupsid
nfqws,tpws: test accessibility of list files after privs drop
nfqws,tpws: --version
v70.4
nfqws,tpws: ^ prefix in hostlist to disable subdomain matches
nfqws,tpws: optional systemd notify support. compile using 'make systemd'
nfqws,tpws: systemd instance templates for nfqws and tpws
nfqws,tpws: separate droproot from dropcaps
tpws: detect WSL 1 and warn about non-working options
v70.5
nfqws: multiple --dpi-desync-fake-xxx
nfqws: support of inter-packet fragmented QUIC CRYPTO
v70.6
nfqws: detect Discord Voice IP discovery packets
nfqws: detect STUN message packets
nfqws: change SNI to specified value tls mod : --dpi-desync-fake-tls-mod sni=<sni>
nfqws: update default TLS ClientHello fake. firefox 136.0.4 finger, no kyber, SNI=microsoft.com
nfqws: multiple mods for multiple TLS fakes
init.d: remove 50-discord
blockcheck: use tpws --fix-seg on linux for multiple splits
v71
nfqws,tpws: debug tls version, alpn, ech
nfqws: --dpi-desync-fake-tls=! means default tls fake
nfqws: --dup*
nfqws: --orig*
nfqws: ipcache of hop count and host names
nfqws: --ctrack-disable
nfqws: --synack-split
nfqws: --autottl=- or --autottl=0:0-0 disable autottl. previous "0" does not work anymore.
tpws: ipcache of host names
nfqws,tpws: set 1024 repeat limit to fakes and dups
nfqws,tpws: do more before daemonize
nfqws,tpws: accept multiple gids in --gid
nfqws,tpws: display "android" in version string if built for android
init.d: remove --ipset parameter prohibition
init.d, blockcheck: drop time exceeded icmp for nfqws-related connections
blockcheck: some dup and orig-ttl mods
blockcheck: PKTWS_EXTRA_PRE
blockcheck: report test function and domain every test
v71.1
nfqws,tpws: much faster ipset implementation. move from hash to avl tree
nfqws,tpws: check list files accessibility with dropped privs in --dry-run mode
nfqws,tpws: --debug=android for NDK builds
nfqws,tpws: use initgroups instead of setgroups if --user specified
nfqws: --filter-ssid (linux-only)
install_easy: stop if running embedded release on traditional linux system (some files missing)
install_bin: add "read elf" arch detection method
binaries: renamed arch dirs in binaries
v71.1.1
nfqws: use wireless ext in case nl80211 does not return SSID
v71.2
nfqws: apply udp desync to replayed packets with non-zero reasm offset (except fake)
blockcheck: display curl version and kernel version
install_bin: stop if no binaries found. display help text.
winws: increase buffers for port filter
tpws: tpws no more opens /dev/pf in OpenBSD by default. requires --enable-pf like in FreeBSD. this is migration from rdr-to to divert-to redirection scheme.
install_easy: warn if --ipset parameter is specified
v71.3
init.d: FILTER_MARK
nfqws: ts fooling
blockcheck: test ts fooling
blockcheck: auto enable tcp timestamps in windows
tpws,nfqws: special handling of IP-like hostnames. strip :port from hostname:port
v71.4
nfqws,tpws: fix possible crashes or high memory usage if hostlist has duplicate hostnames
init.d: custom scripts 50-discord-media, 50-stun4all
init.d: windivert filters for discord media, stun, wireguard
readme: hardware problems description
v72
winws: --wf-raw-part
nfqws: --dpi-desync=hostfakesplit
nfqws: --dpi-desync-fake-tcp-mod=seq
nfqws: --dpi-desync-fake-tls=!+offset , --dpi-desync-fake-xxx=[+offset]@filename
nfqws: --dpi-desync-fakedsplit-mod=altorder for fakedsplit/fakeddisorder
nfqws: --dpi-desync-hostfakesplit-mod=altorder
nfqws: fakedsplit/fakeddisorder normalize fake split pattern offset to reasm offset
nfqws: optimize ipv4 ip_id. apply ip_id on all OS the same way.
blockcheck: print PRETTY_NAME and some OPENWRT_xxx from /etc/os-release
blockcheck: new strategies
blockcheck: curl test simulation : SIMULATE=1
v72.1
nfqws: --ip-id=seq|seqgroup|rnd|zero
blockcheck: MIN_AUTOTTL_DELTA,MAX_AUTOTTL_DELTA
init.d: 50-quic4all custom
72.2
nfqws: --wssize-forced-cutoff
nfqws: --orig-tcp-flags, --dup-tcp-flags, --dpi-desync-tcp-flags
nfqws: --dup-ip-id
73.3
blockcheck: support URIs
blockcheck: CURL_HTTPS_GET=1 suppresses -I curl option for https (HEAD -> GET)
73.4
blockcheck: fix broken dns cache

View File

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

View File

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

View File

@@ -12,7 +12,7 @@ define Package/nfqws
CATEGORY:=Network
TITLE:=nfqws
SUBMENU:=Zapret
DEPENDS:=+libnetfilter-queue +libcap +zlib
DEPENDS:=+libnetfilter-queue +lmnl +libcap +zlib
endef
define Build/Prepare

View File

@@ -2,8 +2,8 @@
> [!CAUTION]
> Не пишите в issue вопросы типа "как скопировать файл", "как скачать", "как
> запустить", ... То есть все , что касается базовых навыков обращения с ОС
> linux. Эти вопросы будут закрывать сразу. Если у вас подобные вопросы
> запустить" и т.п. То есть все, что касается базовых навыков обращения с ОС
> Linux. Эти вопросы будут закрывать сразу. Если у вас подобные вопросы
> возникают, рекомендую не использовать данный софт или искать помощь где-то в
> другом месте. То же самое могу сказать тем, кто хочет нажать 1 кнопку, чтобы
> все заработало, и совсем не хочет читать и изучать. Увы, такое не подвезли и
@@ -16,7 +16,7 @@
в простыню [readme.md](readme.md).
Обход DPI является хакерской методикой. Под этим словом понимается метод,
которому сопротивляется окружающая среда, которому автоматически не
которому оказывается активное противодействие и поэтому автоматически не
гарантирована работоспособность в любых условиях и на любых ресурсах, требуется
настройка под специфические условия у вашего провайдера. Условия могут меняться
со временем, и методика может начинать или переставать работать, может
@@ -52,6 +52,18 @@
1. Скачайте последний [tar.gz релиз](https://github.com/bol-van/zapret/releases) в /tmp, распакуйте его, затем удалите архив.
Для openwrt и прошивок используйте вариант `openwrt-embedded`.
Для экономия места в /tmp можно качать через curl в stdout и сразу распаковывать.
Пример под openwrt для версии zapret 71.4 (для других URL отличается) :
```
$ curl -Lo - https://github.com/bol-van/zapret/releases/download/v71.4/zapret-v71.4-openwrt-embedded.tar.gz | tar -zx
$ wget -O - https://github.com/bol-van/zapret/releases/download/v71.4/zapret-v71.4-openwrt-embedded.tar.gz | tar -zx
```
Пример под традиционный linux для версии zapret 71.4 (для других URL отличается) :
```
$ curl -Lo - https://github.com/bol-van/zapret/releases/download/v71.4/zapret-v71.4.tar.gz | tar -zx
$ wget -O - https://github.com/bol-van/zapret/releases/download/v71.4/zapret-v71.4.tar.gz | tar -zx
```
curl должен быть предварительно установлен. Но он в любом случае понадобится далее.
Вариант с wget будет работать только если установленный wget поддерживает https.
2. Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и
сам zapret. Гарантированно уберет zapret скрипт `uninstall_easy.sh`.
@@ -89,14 +101,15 @@
>
> Проверить работает ли этот вариант можно так:
> ```sh
> $ dig -p 53 @77.88.8.88 rutracker.org dig -p 1253 @77.88.8.88 rutracker.org
> $ dig -p 53 @77.88.8.88 rutracker.org
> $ dig -p 1253 @77.88.8.88 rutracker.org
> ```
>
> Если DNS действительно подменяется, и ответ на эти 2 команды разный,
> значит метод вероятно работает.
>
> В openwrt DNS на нестандартном порту можно прописать в `/etc/config/dhcp`
> таким способом :
> таким способом:
>
> ```
> config dnsmasq
@@ -128,10 +141,14 @@
или `tpws` и запомнить найденные стратегии для дальнейшего применения.
Следует понимать, что скрипт проверяет доступность только конкретного
домена, который вы вводите в начале. Вероятно, все остальные домены
блокированы подобным образом, **но не факт**. В большинстве случаев можно
объединить несколько стратегий в одну универсальную, и это **крайне
желательно**. Необходимо понимать как работают стратегии. zapret **не может
домена, который вы вводите в начале, конкретной программой curl.
У разных клиентов есть свой фингерпринт. У броузеров один, у curl другой.
Может применяться или не применяться многопакетный TLS с постквантовой криптографией (kyber).
От этого может зависеть работоспособность стратегий.
Обычно остальные домены блокированы подобным образом, **но не факт**.
Бывают специальные блокировки. Некоторые параметры требуют тюнинга под "общий знаменатель".
В большинстве случаев можно объединить несколько стратегий в одну универсальную, и это **крайне
желательно**, но это требует понимания как работают стратегии. zapret **не может
пробить блокировку по IP адресу**. Для проверки нескольких доменов вводите
их через пробел.
@@ -142,19 +159,7 @@
> направления (IP сервера). скрипт не всегда может выдать вам в итогах
> оптимальную стратегию, которую надо просто переписать в настройки. В
> некоторых случаях надо реально думать что происходит, анализируя результат
> на разных стратегиях. Если вы применяете большой TTL, чтобы достать до
> магистрала, то не лишним будет добавить дополнительный ограничитель
> `--dpi-desync-fooling`, чтобы не сломать сайты на более коротких
> дистанциях. `md5sig` наиболее совместим, но работает **только** на linux
> серверах. `badseq` может работать только на https и не работать на http.
> Чтобы выяснить какие дополнительные ограничители работают, смотрите
> результат теста аналогичных стратегий без TTL с каждым из этих
> ограничителей.
>
> При использовании `autottl` следует протестировать как можно больше разных
> доменов. Эта техника может на одних провайдерах работать стабильно, на
> других потребуется выяснить при каких параметрах она стабильна, на третьих
> полный хаос, и проще отказаться.
> на разных стратегиях.
>
> Далее, имея понимание что работает на http, https, quic нужно
> сконструировать параметры запуска `tpws` и/или `nfqws` с использованием
@@ -163,7 +168,7 @@
> Если кратко, то обычно параметры конструируются так:
> ```sh
> "--filter-udp=443 'параметры для quic' <HOSTLIST_NOAUTO> --new
> --filter-tcp=80,443 'обьединенные параметры для http и https' <HOSTLIST>"
> --filter-tcp=80,443 'объединенные параметры для http и https' <HOSTLIST>"
> ```
>
> Или так:
@@ -193,7 +198,7 @@
> "--filter-l3=ipv4 --filter-udp=443 lпараметры для quic ipv4' <HOSTLIST_NOAUTO> --new
> --filter-l3=ipv4 --filter-tcp=80 'параметры для http ipv4' <HOSTLIST> --new
> --filter-l3=ipv4 --filter-tcp=443 'параметры для https ipv4' <HOSTLIST> --new
> --filter-l3=ipv6 --filter-udp=443 "параметры для quic ipv6" <HOSTLIST_NOAUTO> --new
> --filter-l3=ipv6 --filter-udp=443 'параметры для quic ipv6' <HOSTLIST_NOAUTO> --new
> --filter-l3=ipv6 --filter-tcp=80 'параметры для http ipv6' <HOSTLIST> --new
> --filter-l3=ipv6 --filter-tcp=443 'параметры для https ipv6' <HOSTLIST>"
> ```
@@ -201,8 +206,8 @@
> Но здесь совсем "копи-пастный" вариант. Чем больше вы объедините стратегий и
> сократите их общее количество, тем будет лучше.
>
> Если вам не нужно дурение отдельных протоколов, лучше всего будет их
> убрать из системы перехвата трафика через параметры `TPWS_PORTS`,
> Если вам не нужно дурение отдельных протоколов, лучше всего будет убрать
> лишние порты из системы перехвата трафика через параметры `TPWS_PORTS`,
> `NFQWS_PORTS_TCP`, `NFQWS_PORTS_UDP` и убрать соответствующие им профили
> мультистратегии.
>
@@ -229,6 +234,15 @@
> В этом примере `wssize` будет применяться всегда к порту tcp `443` вне
> зависимости от параметра `MODE_FILTER`. Хостлист будет игнорироваться,
> если таковой имеется. К http применять `wssize` вредно и бессмысленно.
>
> Иногда требуется дописать к стратегиям свои собственные параметры.
> Например, нужно изменить количество повторов фейков или задать свой фейк.
> Это делается через шелл-переменные `PKTWS_EXTRA`, `TPWS_EXTRA`.
>
> ```PKTWS_EXTRA="--dpi-desync-repeats=10 --dpi-desync-fake-tls=/tmp/tls.bin" ./blockcheck.sh```
>
> Перебор всех комбинаций может привести к ожиданию неделями, поэтому выбран разумный
> костяк проверки, на который вы можете навешивать свои кустомизации.
7. Запустите скрипт облегченной установки - `install_easy.sh` Выберите `nfqws`
и/или `tpws`, затем согласитесь на редактирование параметров. Откроется

View File

@@ -11,8 +11,8 @@
## Немного разъяснений
Обход DPI является хакерской методикой. Под этим словом понимается метод, которому сопротивляется окружающая среда,
которому автоматически не гарантирована работоспособность в любых условиях и на любых ресурсах,
Обход DPI является хакерской методикой. Под этим словом понимается метод, которому оказывается активное противодействие и поэтому
автоматически не гарантирована работоспособность в любых условиях и на любых ресурсах,
требуется настройка под специфические условия у вашего провайдера. Условия могут меняться со временем,
и методика может начинать или переставать работать, может потребоваться повторный анализ ситуации.
Могут обнаруживаться отдельные ресурсы, которые заблокированы иначе, и которые не работают или перестали работать.
@@ -30,24 +30,7 @@
Будем считать, что у вас есть windows 7 или выше. Задача - обойти блокировки с самой системы.
> [!NOTE]
> Есть решение самое простое, а есть "как положено".
## САМОЕ ПРОСТОЕ РЕШЕНИЕ
_"Совсем ничего не могу, все очень сложно, дайте мне таблетку."_ ©Простой пользователь
1) Скачайте и распакуйте архив https://github.com/bol-van/zapret-win-bundle/archive/refs/heads/master.zip.
2) Запустите `zapret-winws/preset_russia.cmd` от имени администратора. Возможно, заведется сразу.
> То же самое с ограничителем по автоматически создаваемому хост-листу `preset_russia_autohostlist.cmd`.
> Что такое `autohostlist` - читайте [readme.md](./readme.md). Проще говоря, мы обходим только то, что долго и упорно не хочет открываться.
> Сначала не будет, но надо пытаться много раз, и тогда сработает, а дальше будет всегда срабатывать.
> Остальное не будет ломаться. Использовать только, если первый вариант тоже работает.
Не помогла _"таблетка"_ ? Это вовсе не значит, что ничего не получится. Но придется делать по нормальному.
## НЕ ПОМОГЛО, КАК ТЕПЕРЬ ЭТО УДАЛИТЬ
## Я ЧТО-ТО ДЕЛАЛ, НЕ ПОМОГЛО, КАК ТЕПЕРЬ ЭТО УДАЛИТЬ
Если вы не устанавливали zapret как службу или запланированную задачу (а это требует редактирования cmd файлов),
достаточно закрыть окно с winws и запустить windivert_delete.cmd.
@@ -55,14 +38,17 @@ _"Совсем ничего не могу, все очень сложно, да
После чего можно удалить папку с zapret. На этом деинсталляция закончена.
Если же вы устанавливали zapret как службу, то вы наверняка знаете как ее удалить.
## РЕШЕНИЕ "КАК ПОЛОЖЕНО"
Если вдруг среди того, на что вы нажимали, есть слова "general", "alt", ".bat", "автозапуск", или же есть файлы, которые отсутствуют
в оригинальных репозиториях, то это сборка. Вы не получите ответа как ее удалить от разработчика zapret.
Спрашивайте самих сборщиков. Разработчик не предоставляет простого решения, этим занимаются сборщики, но они и сами отвечают за свои продукты.
1) Скачайте и распакуйте архив https://github.com/bol-van/zapret-win-bundle/archive/refs/heads/master.zip.
## Настройка
2) Если у вас Windows 7 x64, однократно запустите `win7/install_win7.cmd`. Батник заменит файлы windivert на совместимую с Windows 7 версию.
1. Скачайте и распакуйте архив https://github.com/bol-van/zapret-win-bundle/archive/refs/heads/master.zip.
> [!WARNING]
> Для 32-битных систем Windows нет готового полного варианта.
2. Если у вас Windows 7 x64, однократно запустите `win7/install_win7.cmd`. Батник заменит файлы windivert на совместимую с Windows 7 версию.
> Для 32-битных систем Windows нет готового полного варианта.
> На windows 11 arm64 выполните `arm64/install_arm64.cmd` от имени администратора и перезагрузите компьютер.
> Читайте [docs/windows.md](./windows.md)
@@ -72,15 +58,15 @@ _"Совсем ничего не могу, все очень сложно, да
> более-менее научились с ним дружить.
> Если проблема имеет место , используйте исключения. Если не помогает - отключайте антивирус совсем.
3) Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и сам zapret.
3. Убедитесь, что у вас отключены все средства обхода блокировок, в том числе и сам zapret.
4) Если вы работаете в виртуальной машине, необходимо использовать соединение с сетью в режиме bridge. nat не подходит
4. Если вы работаете в виртуальной машине, необходимо использовать соединение с сетью в режиме bridge. nat не подходит
5) Запустите `blockcheck\blockcheck.cmd`. blockcheck в начале проверяет **DNS**.
Если выводятся сообщения о подмене адресов, то нужно будет решить проблему с **DNS**.
blockcheck перейдет в этом случае на **DoH** _(DNS over HTTPS)_ и будет пытаться получить и использовать реальные IP адреса.
Но если вы не настроите решение этой проблемы, обход будет работать только для тех программ,
которые сами реализуют механизмы SecureDNS. Для других программ обход работать не будет.
5. Запустите `blockcheck\blockcheck.cmd`. blockcheck в начале проверяет **DNS**.
Если выводятся сообщения о подмене адресов, то нужно будет решить проблему с **DNS**.
blockcheck перейдет в этом случае на **DoH** _(DNS over HTTPS)_ и будет пытаться получить и использовать реальные IP адреса.
Но если вы не настроите решение этой проблемы, обход будет работать только для тех программ,
которые сами реализуют механизмы SecureDNS. Для других программ обход работать не будет.
> Решение проблемы DNS выходит за рамки проекта. Обычно она решается либо заменой DNS серверов
> от провайдера на публичные (`1.1.1.1`, `8.8.8.8`), либо в случае перехвата провайдером обращений
@@ -92,35 +78,29 @@ blockcheck перейдет в этом случае на **DoH** _(DNS over HTT
>
> Тут все разжевано как и где это включается : https://hackware.ru/?p=13707
6) blockcheck позволяет выявить рабочую стратегию обхода блокировок.
Лог скрипта будет сохранен в `blockcheck\blockcheck.log`.
Запомните/перепишите найденные стратегии.
6. blockcheck позволяет выявить рабочую стратегию обхода блокировок.
Лог скрипта будет сохранен в `blockcheck\blockcheck.log`.
Запомните/перепишите найденные стратегии.
> [!WARNING]
> Следует понимать, что blockcheck проверяет доступность только конкретного домена, который вы вводите в начале.
> Вероятно, все остальные домены блокированы подобным образом, но не факт.
Следует понимать, что скрипт проверяет доступность только конкретного
домена, который вы вводите в начале, конкретной программой curl.
У разных клиентов есть свой фингерпринт. У броузеров один, у curl другой.
Может применяться или не применяться многопакетный TLS с постквантовой криптографией (kyber).
От этого может зависеть работоспособность стратегий.
Обычно остальные домены блокированы подобным образом, **но не факт**.
Бывают специальные блокировки. Некоторые параметры требуют тюнинга под "общий знаменатель".
В большинстве случаев можно объединить несколько стратегий в одну универсальную, и это **крайне
желательно**, но это требует понимания как работают стратегии. zapret **не может
пробить блокировку по IP адресу**. Для проверки нескольких доменов вводите их через пробел.
> [!TIP]
> В большинстве случаев можно обьединить несколько стратегий в одну универсальную, и это крайне желательно.
> Необходимо понимать [как работают стратегии](./readme.md/#nfqws).
> zapret не может пробить блокировку по IP адресу. Для проверки нескольких доменов вводите их через пробел.
>
> Сейчас блокираторы ставят на магистральных каналах. В сложных случаях у вас может быть несколько маршрутов
> с различной длиной по ХОПам, с DPI на разных хопах. Приходится преодолевать целый зоопарк DPI,
> которые еще и включаются в работу хаотичным образом или образом, зависящим от направления (IP сервера).
> blockcheck не всегда может выдать вам в итогах оптимальную стратегию, которую надо просто переписать в настройки.
> В некоторых случаях надо реально думать что происходит, анализируя результат на разных стратегиях.
> Если вы применяете большой TTL, чтобы достать до магистрала, то не лишним будет добавить дополнительный ограничитель
> `--dpi-desync-fooling`, чтобы не сломать сайты на более коротких дистанциях.
> _md5sig_ наиболее совместим, но работатет только на linux серверах.
> badseq может работать только на https и не работать на http.
> Чтобы выяснить какие дополнительные ограничители работают, смотрите результат теста аналогичных стратегий без TTL
> с каждым из этих ограничителей.
>
> При использовании autottl следует протестировать как можно больше разных доменов. Эта техника
> может на одних провайдерах работать стабильно, на других потребуется выяснить при каких параметрах
> она стабильна, на третьих полный хаос, и проще отказаться.
> Сейчас блокираторы ставят на магистральных каналах. В сложных случаях у
> вас может быть несколько маршрутов с различной длиной по ХОПам, с DPI на
> разных хопах. Приходится преодолевать целый зоопарк DPI, которые еще и
> включаются в работу хаотичным образом или образом, зависящим от
> направления (IP сервера). скрипт не всегда может выдать вам в итогах
> оптимальную стратегию, которую надо просто переписать в настройки. В
> некоторых случаях надо реально думать что происходит, анализируя результат
> на разных стратегиях.
>
> Далее, имея понимание что работает на http, https, quic, нужно сконструировать параметры запуска winws
> с использованием мультистратегии. Как работают мультистратегии описано в [readme.md](./readme.md#множественные-стратегии).
@@ -183,12 +163,21 @@ blockcheck перейдет в этом случае на **DoH** _(DNS over HTT
>
> В этих примерах wssize будет применяться всегда к порту tcp 443, а хостлист будет игнорироваться.
> К http применять wssize вредно и бессмысленно.
>
> Иногда требуется дописать к стратегиям свои собственные параметры.
> Например, нужно изменить количество повторов фейков или задать свой фейк.
> Это делается через шелл-переменные `PKTWS_EXTRA`, `TPWS_EXTRA`. Пользуйтесь шеллом `cygwin/cygwin-admin.cmd`.
>
> ```PKTWS_EXTRA="--dpi-desync-repeats=10 --dpi-desync-fake-tls=/tmp/tls.bin" blockcheck```
>
> Перебор всех комбинаций может привести к ожиданию неделями, поэтому выбран разумный
> костяк проверки, на который вы можете навешивать свои кустомизации.
7) Протестируйте найденные стратегии на winws. Winws следует брать из zapret-winws.
Для этого откройте командную строку windows от имени администратора в директории zapret-winws.
Проще всего это сделать через `_CMD_ADMIN.cmd`. Он сам поднимет права и зайдет в нужную директорию.
7. Протестируйте найденные стратегии на winws. Winws следует брать из zapret-winws.
Для этого откройте командную строку windows от имени администратора в директории zapret-winws.
Проще всего это сделать через `_CMD_ADMIN.cmd`. Он сам поднимет права и зайдет в нужную директорию.
8) Обеспечьте удобную загрузку обхода блокировок.
8. Обеспечьте удобную загрузку обхода блокировок.
> Есть 2 варианта. Ручной запуск через ярлык или автоматический при старте системы, вне контекста текущего пользователя.
> Последний вариант разделяется на запуск через планировщик задач и через службы windows.
@@ -203,11 +192,11 @@ blockcheck перейдет в этом случае на **DoH** _(DNS over HTT
>
> Аналогично настраиваются и службы windows. Смотрите `service_*.cmd`
9) Если ломаются отдельные незаблокированные ресурсы, нужно пользоваться ограничивающим
ipset или хост листом. Читайте основной талмуд [readme.md](./readme.md) ради подробностей.
Но еще лучше будет подбирать такие стратегии, которые ломают минимум.
Есть стратегии довольно безобидные, а есть сильно ломающие, которые подходят только для точечного пробития отдельных ресурсов,
когда ничего лучше нет. Хорошая стратегия может сильно ломать из-за плохо подобранных ограничителей для фейков - ttl, fooling.
9. Если ломаются отдельные незаблокированные ресурсы, нужно пользоваться ограничивающим
ipset или хост листом. Читайте основной талмуд [readme.md](./readme.md) ради подробностей.
Но еще лучше будет подбирать такие стратегии, которые ломают минимум.
Есть стратегии довольно безобидные, а есть сильно ломающие, которые подходят только для точечного пробития отдельных ресурсов,
когда ничего лучше нет. Хорошая стратегия может сильно ломать из-за плохо подобранных ограничителей для фейков - ttl, fooling.
> [!CAUTION]
> Это минимальная инструкция, чтобы соориентироваться с чего начать. Однако, это - не панацея.

View File

@@ -1,9 +1,10 @@
# zapret v69.8
# zapret v72.2
# SCAMMER WARNING
This software is free and open source under [MIT license](./LICENSE.txt).
If anyone demands you to download this software only from their webpage, telegram channel, forces you to delete links, videos, makes copyright claims, you are dealing with scammers.
However, [donations](#donations) are welcome.
# Multilanguage/Мультиязычный README
___
@@ -19,20 +20,28 @@ ___
- [nfqws](#nfqws)
- [DPI desync attack](#dpi-desync-attack)
- [Fakes](#fakes)
- [Fake mods](#fake-mods)
- [TCP segmentation](#tcp-segmentation)
- [Sequence numbers overlap](#sequence-numbers-overlap)
- [IP_ID assignment](#ip_id-assignment)
- [ipv6 specific modes](#ipv6-specific-modes)
- [Original modding](#original-modding)
- [Duplicates](#duplicates)
- [Server reply reaction](#server-reply-reaction)
- [SYNDATA mode](#syndata-mode)
- [DPI desync combos](#dpi-desync-combos)
- [IP cache](#ip-cache)
- [CONNTRACK](#conntrack)
- [Reassemble](#reassemble)
- [UDP support](#udp-support)
- [IP fragmentation](#ip-fragmentation)
- [Multiple strategies](#multiple-strategies)
- [WIFI filtering](#wifi-filtering)
- [Virtual machines](#virtual-machines)
- [IPTABLES for nfqws](#iptables-for-nfqws)
- [NFTABLES for nfqws](#nftables-for-nfqws)
- [Flow offloading](#flow-offloading)
- [Server side fooling](#server-side-fooling)
- [tpws](#tpws)
- [TCP segmentation in tpws](#tcp-segmentation-in-tpws)
- [TLSREC](#tlsrec)
@@ -119,7 +128,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
@@ -128,81 +137,126 @@ For BSD systems there is dvtws. Its built from the same source and has almost th
nfqws takes the following parameters:
```
@<config_file> ; read file for options. must be the only argument. other options are ignored.
@<config_file> ; read file for options. must be the only argument. other options are ignored.
--debug=0|1
--dry-run ; verify parameters and exit with code 0 if successful
--comment ; any text (ignored)
--dry-run ; verify parameters and exit with code 0 if successful
--version ; print version and exit
--comment ; any text (ignored)
--qnum=<nfqueue_number>
--daemon ; daemonize
--pidfile=<filename> ; write pid to file
--user=<username> ; drop root privs
--uid=uid[:gid] ; drop root privs
--bind-fix4 ; apply outgoing interface selection fix for generated ipv4 packets
--bind-fix6 ; apply outgoing interface selection fix for generated ipv6 packets
--wsize=<window_size>[:<scale_factor>] ; set window size. 0 = do not modify. OBSOLETE !
--wssize=<window_size>[:<scale_factor>] ; set window size for server. 0 = do not modify. default scale_factor = 0.
--wssize-cutoff=[n|d|s]N ; apply server wsize only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
--ctrack-timeouts=S:E:F[:U] ; internal conntrack timeouts for TCP SYN, ESTABLISHED, FIN stages, UDP timeout. default 60:300:60:60
--hostcase ; change Host: => host:
--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
--dpi-desync-ttl6=<int> ; set ipv6 hop limit for desync packet. by default ttl value is used.
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]] ; auto ttl mode for both ipv4 and ipv6. default: 1:3-20
--dpi-desync-autottl6=[<delta>[:<min>[-<max>]]] ; overrides --dpi-desync-autottl for ipv6 only
--dpi-desync-fooling=<mode>[,<mode>] ; can use multiple comma separated values. modes : none md5sig ts badseq badsum datanoack hopbyhop hopbyhop2
--dpi-desync-repeats=<N> ; send every desync packet N times
--dpi-desync-skip-nosni=0|1 ; 1(default)=do not act on ClientHello without SNI (ESNI ?)
--dpi-desync-split-pos=N|-N|marker+N|marker-N ; comma separated list of split positions
; markers: method,host,endhost,sld,endsld,midsld,sniext
; full list is only used by multisplit and multidisorder
; fakedsplit/fakeddisorder use first l7-protocol-compatible parameter if present, first abs value otherwise
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; use sequence overlap before first sent original split segment
--dpi-desync-split-seqovl-pattern=<filename>|0xHEX ; pattern for the fake part of overlap
--dpi-desync-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
--dpi-desync-badack-increment=<int|0xHEX> ; badseq fooling ackseq signed increment. default -66000
--dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet
--dpi-desync-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-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
--dpi-desync-fake-wireguard=<filename>|0xHEX ; file containing fake wireguard handshake initiation
--dpi-desync-fake-dht=<filename>|0xHEX ; file containing fake DHT (d1..e)
--dpi-desync-fake-unknown-udp=<filename>|0xHEX ; file containing unknown udp protocol fake payload
--dpi-desync-udplen-increment=<int> ; increase or decrease udp packet length by N bytes (default 2). negative values decrease length.
--dpi-desync-udplen-pattern=<filename>|0xHEX ; udp tail fill pattern
--dpi-desync-start=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N
--dpi-desync-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 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
--daemon ; daemonize
--pidfile=<filename> ; write pid to file
--user=<username> ; drop root privs
--uid=uid[:gid1,gid2,...] ; drop root privs
--bind-fix4 ; apply outgoing interface selection fix for generated ipv4 packets
--bind-fix6 ; apply outgoing interface selection fix for generated ipv6 packets
--wsize=<window_size>[:<scale_factor>] ; set window size. 0 = do not modify. OBSOLETE !
--wssize=<window_size>[:<scale_factor>] ; set window size for server. 0 = do not modify. default scale_factor = 0.
--wssize-cutoff=[n|d|s]N ; apply server wsize only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
--wssize-forced-cutoff=0|1 ; 1(default)=auto cutoff wssize on known protocol
--ctrack-timeouts=S:E:F[:U] ; internal conntrack timeouts for TCP SYN, ESTABLISHED, FIN stages, UDP timeout. default 60:300:60:60
--ctrack-disable=[0|1] ; 1 or no argument disables conntrack
--ipcache-lifetime=<int> ; time in seconds to keep cached hop count and domain name (default 7200). 0 = no expiration
--ipcache-hostname=[0|1] ; 1 or no argument enables ip->hostname caching
--hostcase ; change Host: => host:
--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:
--synack-split=[syn|synack|acksyn] ; perform TCP split handshake : send SYN only, SYN+ACK or ACK+SYN
--orig-ttl=<int> ; set TTL for original packets
--orig-ttl6=<int> ; set ipv6 hop limit for original packets. by default ttl value is used
--orig-autottl=[<delta>[:<min>[-<max>]]|-] ; auto ttl mode for both ipv4 and ipv6. default: +5:3-64. "0:0-0" or "-" disables autottl.
--orig-autottl6=[<delta>[:<min>[-<max>]]|-] ; overrides --orig-autottl for ipv6 only
--orig-tcp-flags-set=<int|0xHEX|flaglist> ; set these tcp flags (flags |= value). value can be int, hex or comma separated list : FIN,SYN,RST,PSH,ACK,URG,ECE,CWR,AE,R1,R2,R3
--orig-tcp-flags-unset=<int|0xHEX|flaglist> ; unset these tcp flags (flags &= ~value)
--orig-mod-start=[n|d|s]N ; apply orig TTL mod to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N
--orig-mod-cutoff=[n|d|s]N ; apply orig TTL mod to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
--dup=<int> ; duplicate original packets. send N dups before original.
--dup-replace=[0|1] ; 1 or no argument means do not send original, only dups
--dup-ttl=<int> ; set TTL for dups
--dup-ttl6=<int> ; set ipv6 hop limit for dups. by default ttl value is used
--dup-autottl=[<delta>[:<min>[-<max>]]|-] ; auto ttl mode for both ipv4 and ipv6. default: -1:3-64. "0:0-0" or "-" disables autottl.
--dup-autottl6=[<delta>[:<min>[-<max>]]|-] ; overrides --dup-autottl for ipv6 only
--dup-tcp-flags-set=<int|0xHEX|flaglist> ; set these tcp flags (flags |= value). value can be int, hex or comma separated list : FIN,SYN,RST,PSH,ACK,URG,ECE,CWR,AE,R1,R2,R3
--dup-tcp-flags-unset=<int|0xHEX|flaglist> ; unset these tcp flags (flags &= ~value)
--dup-fooling=<mode>[,<mode>] ; can use multiple comma separated values. modes : none md5sig badseq badsum datanoack hopbyhop hopbyhop2
--dup-ts-increment=<int|0xHEX> ; ts fooling TSval signed increment for dup. default -600000
--dup-badseq-increment=<int|0xHEX> ; badseq fooling seq signed increment for dup. default -10000
--dup-badack-increment=<int|0xHEX> ; badseq fooling ackseq signed increment for dup. default -66000
--dup-ip-id=same|zero|seq|rnd ; ipv4 ip_id mode for dupped packets
--dup-start=[n|d|s]N ; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N
--dup-cutoff=[n|d|s]N ; apply dup to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
--ip-id=zero|seq|seqgroup|rnd ; ipv4 ip_id assignment scheme
--dpi-desync=[<mode0>,]<mode>[,<mode2>] ; try to desync dpi state. modes : synack fake fakeknown rst rstack hopbyhop destopt ipfrag1 multisplit multidisorder fakedsplit hostfakesplit fakeddisorder ipfrag2 udplen tamper
--dpi-desync-fwmark=<int|0xHEX> ; override fwmark for desync packet. default = 0x40000000 (1073741824)
--dpi-desync-ttl=<int> ; set ttl for desync packet
--dpi-desync-ttl6=<int> ; set ipv6 hop limit for desync packet. by default ttl value is used.
--dpi-desync-autottl=[<delta>[:<min>[-<max>]]|-] ; auto ttl mode for both ipv4 and ipv6. default: -1:3-20. "0:0-0" or "-" disables autottl.
--dpi-desync-autottl6=[<delta>[:<min>[-<max>]]|-] ; overrides --dpi-desync-autottl for ipv6 only
--dpi-desync-tcp-flags-set=<int|0xHEX|flaglist> ; set these tcp flags (flags |= value). value can be int, hex or comma separated list : FIN,SYN,RST,PSH,ACK,URG,ECE,CWR,AE,R1,R2,R3
--dpi-desync-tcp-flags-unset=<int|0xHEX|flaglist> ; unset these tcp flags (flags &= ~value)
--dpi-desync-fooling=<mode>[,<mode>] ; can use multiple comma separated values. modes : none md5sig ts badseq badsum datanoack hopbyhop hopbyhop2
--dpi-desync-repeats=<N> ; send every desync packet N times
--dpi-desync-skip-nosni=0|1 ; 1(default)=do not act on ClientHello without SNI (ESNI ?)
--dpi-desync-split-pos=N|-N|marker+N|marker-N ; comma separated list of split positions
; markers: method,host,endhost,sld,endsld,midsld,sniext
; full list is only used by multisplit and multidisorder
; fakedsplit/fakeddisorder use first l7-protocol-compatible parameter if present, first abs value otherwise
--dpi-desync-split-seqovl=N|-N|marker+N|marker-N ; use sequence overlap before first sent original split segment
--dpi-desync-split-seqovl-pattern=[+ofs]@<filename>|0xHEX ; pattern for the fake part of overlap
--dpi-desync-fakedsplit-pattern=[+ofs]@<filename>|0xHEX ; fake pattern for fakedsplit/fakeddisorder
--dpi-desync-fakedsplit-mod=mod[,mod] ; mods can be none,altorder=0|1|2|3 + 0|8|16
--dpi-desync-hostfakesplit-midhost=marker+N|marker-N ; additionally split real hostname at specified marker. must be within host..endhost or won't be splitted.
--dpi-desync-hostfakesplit-mod=mod[,mod] ; can be none, host=<hostname>, altorder=0|1
--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-ts-increment=<int|0xHEX> ; ts fooling TSval signed increment. default -600000
--dpi-desync-badseq-increment=<int|0xHEX> ; badseq fooling seq signed increment. default -10000
--dpi-desync-badack-increment=<int|0xHEX> ; badseq fooling ackseq signed increment. default -66000
--dpi-desync-any-protocol=0|1 ; 0(default)=desync only http and tls 1=desync any nonempty data packet
--dpi-desync-fake-tcp-mod=mod[,mod] ; comma separated list of tcp fake mods. available mods : none,seq
--dpi-desync-fake-http=[+ofs]@<filename>|0xHEX ; file containing fake http request
--dpi-desync-fake-tls=[+ofs]@<filename>|0xHEX|![+offset] ; file containing fake TLS ClientHello (for https). '!' = standard fake
--dpi-desync-fake-tls-mod=mod[,mod] ; comma separated list of TLS fake mods. available mods : none,rnd,rndsni,sni=<sni>,dupsid,padencap
--dpi-desync-fake-unknown=[+ofs]@<filename>|0xHEX ; file containing unknown protocol fake payload
--dpi-desync-fake-syndata=[+ofs]@<filename>|0xHEX ; file containing SYN data payload
--dpi-desync-fake-quic=[+ofs]@<filename>|0xHEX ; file containing fake QUIC Initial
--dpi-desync-fake-wireguard=[+ofs]@<filename>|0xHEX ; file containing fake wireguard handshake initiation
--dpi-desync-fake-dht=[+ofs]@<filename>|0xHEX ; file containing fake DHT (d1..e)
--dpi-desync-fake-discord=[+ofs]@<filename>|0xHEX ; file containing fake Discord voice connection initiation packet (IP Discovery)
--dpi-desync-fake-stun=[+ofs]@<filename>|0xHEX ; file containing fake STUN message
--dpi-desync-fake-unknown-udp=[+ofs]@<filename>|0xHEX ; file containing unknown udp protocol fake payload
--dpi-desync-udplen-increment=<int> ; increase or decrease udp packet length by N bytes (default 2). negative values decrease length.
--dpi-desync-udplen-pattern=[+ofs]@<filename>|0xHEX ; udp tail fill pattern
--dpi-desync-start=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) greater or equal than N
--dpi-desync-cutoff=[n|d|s]N ; apply dpi desync only to packet numbers (n, default), data packet numbers (d), relative sequence (s) less than N
--hostlist=<filename> ; apply dpi desync only to the listed hosts (one host per line, subdomains auto apply if not prefixed with `^`, gzip supported, multiple hostlists allowed)
--hostlist-domains=<domain_list> ; comma separated fixed domain list
--hostlist-exclude=<filename> ; do not apply dpi desync to the listed hosts (one host per line, subdomains auto apply if not prefixed with `^`, gzip supported, multiple hostlists allowed)
--hostlist-exclude-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 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=<proto> ; L6-L7 protocol filter. multiple comma separated values allowed. proto: http tls quic wireguard dht discord stun unknown
--filter-ssid=ssid1[,ssid2,ssid3,...] ; per profile wifi SSID filter
--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
```
Many parameters dealing with binary data support loading from hex string prefixed by "0x" or from a file.
Filename can be "as is" or prefixed with "@". If there's "+number" prefix before "@" it means offset of data inside the file.
Offset must be less that data size.
### DPI desync attack
The idea is to take original message, modify it, add additional fake information in such a way that the server OS accepts original data only
@@ -216,7 +270,9 @@ There're attacks based on TCP sequence numbers. Methods can be combined in many
Fakes are separate generated by nfqws packets carrying false information for DPI. They must either not reach the server or be rejected by it. Otherwise TCP connection or data stream would be broken. There're multiple ways to solve this task.
* **md5sig** does not work on all servers
* **md5sig** does not work on all servers. It typically works only on Linux servers. MD5 tcp option requires additional space in TCP header
and can cause MTU overflow during fakedsplit/fakeddisorder on low positions when multisegment query (TLS kyber) is transmitted.
`nfqws` cannot redistribute data between original TCP segments. The error displayed is 'message too long'.
* **badsum** doesn't work if your device is behind NAT which does not pass invalid packets.
The most common Linux NAT router configuration does not pass them. Most home routers are Linux based.
The default sysctl configuration `net.netfilter.nf_conntrack_checksum=1` causes contrack to verify tcp and udp checksums
@@ -250,10 +306,23 @@ Fakes are separate generated by nfqws packets carrying false information for DPI
* **datanoack** sends tcp fakes without ACK flag. Servers do not accept this but DPI may accept.
This mode may break NAT and may not work with iptables if masquerade is used, even from the router itself.
Works with nftables properly. Likely requires external IP address (some ISPs pass these packets through their NAT).
* **autottl** tries to automatically guess TTL value that allows DPI to receive fakes and does not allow them to reach the server.
This tech relies on well known TTL values used by OS : 64,128,255. nfqws takes first incoming packet (YES, you need to redirect it too),
guesses path length and decreases by `delta` value (default 1). If resulting value is outside the range (min,max - default 3,20)
then its normalized to min or max. If the path shorter than the value then autottl fails and falls back to the fixed value.
* Manipulate **tcp flags** with `--dpi-desync-tcp-flags-set` and `--dpi-desync-tcp-flags-unset`.
Invalid tcp flags combination may cause server to drop the packet but DPI can accept it.
For example, set SYN in fakes. This may not work with all servers.
`datanoack` can be replaced to `--dpi-desync-tcp-flags-unset=ACK`.
* **ts** adds to TSval ts increment value (-600000 by default). Servers discard packets with TSval in some range.
Practical tests suggest increment between -100 and -0x80000000.
Timestamps are generated by client OS. In linux timestamps are enabled by default. In windows by default timestamps are disabled.
They can be enabled with this command : `netsh interface tcp set global timestamps=enabled` .
ts fooling requires that timestamps are enabled. They must be enabled on every client OS.
TSecr is left unmodified.
* **autottl** tries to automatically guess hop count to the server and compute TTL by adding some delta value that can be positive or negative.
Positive deltas must be preceeded by unary `+` sign. Deltas without any unary sign are treated negative for old versions compatibility reasons.
This tech relies on well known TTL default values used by OS : 64,128,255.
nfqws needs first incoming packet to see it's TTL. You must redirect it too.
If resulting value TTL is outside the range (min,max) then its normalized to min or max.
If delta is negative and TTL is longer than guessed hop count or delta is positive and TTL is shorter than guessed hop count
then autottl fails and falls back to the fixed value.
This can help if multiple DPIs exists on backbone channels, not just near the ISP.
Can fail if inbound and outbound paths are not symmetric.
@@ -261,12 +330,75 @@ Fakes are separate generated by nfqws packets carrying false information for DPI
`--dpi-desync-fooling` takes multiple comma separated values.
Multiple parameters `--dpi-desync-fake-???` are supported except for the `--dpi-desync-fake-syndata`.
Fakes are sent in the specified order. `--dpi-desync-repeats` resends each fake.
Resulting order would be : `fake1 fake1 fake1 fake2 fake2 fake2 fake3 fake3 fake3 .....`
### FAKE mods
By default all tcp fakes are sent with the same sequence as original packet.
This can be changed by `--dpi-desync-fake-tcp-mod=seq`. In the latter case all fakes are sent as if they would be tcp segments of a single fake.
**nfqws** has built-in TLS fake. It can be customized with `--dpi-desync-fake-tls` option.
Customized fake data can be anything - valid TLS Client Hello or arbitrary data.
It's possible to use TLS Client Hello with any fingerprint and any SNI.
**nfqws** can do some modifications of valid TLS Client Hello fakes in runtime with `--dpi-desync-fake-tls-mod` option.
* `none`. Do not do any mods.
* `rnd`. Randomize `random` and `session id` fields. Applied on every request.
* `rndsni`. Randomize SNI. If SNI >=7 symbols random SLD is applied with known TLD. Otherwise filled with random symbols. Applied only once at startup.
* `dupsid`. Copy `session ID` from original TLS Client Hello. Takes precedence over `rnd`. Applied on every request.
* `sni=<sni>`. Set specified SNI value. Changes TLS fake length, fixes lengths in TLS structure. Applied once at startup before `rndsni`.
* `padencap`. Padding extension is extended by original TLS Client Hello size (including multi packet variation with kyber). Padding extension is added to the end if not present, otherwise it must be the last extension. All lengths are increased. Fake size is not changed. Can be useful if DPI does not analyze sequence numbers properly. Applied on every request.
By default if custom fake is not defined `rnd,rndsni,dupsid` mods are applied. If defined - `none`.
This behaviour is compatible with previous versions with addition of `dupsid`.
If multiple TLS fakes are present each one takes the last mod.
If a mod is specified after fake it replaces previous mod.
This way it's possible to use different mods for every TLS fake.
If a mod is set to non-TLS fake it causes error. Use `--dpi-desync-fake-tls-mod=none'.
Example : `--dpi-desync-fake-tls=iana_org.bin --dpi-desync-fake-tls-mod=rndsni --dpi-desync-fake-tls=0xaabbccdd --dpi-desync-fake-tls-mod=none'
### TCP segmentation
* `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, 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
* `fakedsplit`. sequental one position split with fake mix
* `hostfakesplit` (altorder=0). fake host part of the request : before host, random fake host, real host (optionally split this part), random fake host repeat, after host
* `hostfakesplit` (altorder=1). fake host part of the request : before host, random fake host, after host, real host (optionally split this part)
* `fakedsplit`. reverse one position split with fake mix
`--dpi-desync-fakedsplit-mod=altorder=N` specifies number which influence to the presence of individual fakes in `fakedsplit`/`fakeddisorder`.
`fakedsplit` TCP segments of multi-packet messages with split pos :
* `altorder=0`. fake 1st segment, 1st segment, fake 1st segment, fake 2nd segment, 2nd segment, fake 2nd segment
* `altorder=1`. 1st segment, fake 1st segment, fake 2nd segment, 2nd segment, fake 2nd segment
* `altorder=2`. 1st segment, fake 2nd segment, 2nd segment, fake 2nd segment
* `altorder=3`. 1st segment, fake 2nd segment, 2nd segment
`fakeddisorder` TCP segments of multi-packet messages with split pos :
* `altorder=0`. fake 2nd segment, 2nd segment, fake 2nd segment, fake 1st segment, 1st segment, fake 1st segment
* `altorder=1`. 2nd segment, fake 2nd segment, fake 1st segment, 1st segment, fake 1st segment
* `altorder=2`. 2nd segment, fake 1st segment, 1st segment, fake 1st segment
* `altorder=3`. 1st segment, fake 1st segment, 1st segment
`fakedsplit`/`fakeddisorder` TCP segments of multi-packet messages without split pos :
* `altorder=0`. fake, original, fake
* `altorder=8`. original, fake
* `altorder=16`. original
Resulting `altorder=N` is the sum of two `altorder` parts mentioned above.
`--dpi-desync-fakedsplit-pattern` defines data payload of fakes in `fakedsplit`/`fakeddisorder`. By default pattern is simple `0x00`.
Offset of split part + offset of current packet in multi-packet message define offset in the pattern.
Positions are defined by markers.
@@ -295,6 +427,22 @@ First relative markers are searched. If no suitable found absolute markers are s
For example, `--dpi-desync-split-pos=method+2,midsld,5` means `method+2` for http, `midsld` for TLS and 5 for others.
`--dpi-desync-fakedsplit-mod=altorder=N` switches `fakedsplit` to alternate segment ordering.
`hostfakesplit` only fakes hostname part of the request making it hard to destinguish between real and fake host names.
It works for tcp protocols with host : TLS and HTTP. Real hostname can be additionally split using `--dpi-desync-hostfakesplit-midhost` marker.
For example, `--dpi-desync-hostfakesplit-midhost=midsld`. Position must be within host range or split won't happen.
Multi-packet queries are supported if hostname part is not already split. If it is fooling is cancelled.
By default fake host names are generated randomly on the fly using `[0-9a-z]` pattern. If host length is >= 7 dot is placed to simulate 3-char TLD and last 3 chars are replaces with a random known 3-char TLD.
It's possible to set fake host template : `--dpi-desync-hostfakesplit-mod=host=<hostname>`.
Template hostname will be expanded to the left to original hostname size with random characters from `[0-9a-z]` pattern : "www.networksolutions.com" -> "h8xmdba4tv7a8.google.com".
If original hostname size is less than template size it will be cut : "habr.com" -> "ogle.com".
If original hostname size is larger than template size by one, dot will be appended to the left : "www.xxx.com" => ".google.com"..
That's why it's a good idea to use short hostnames in template : "ya.ru", "vk.com", "x.com".
`--dpi-desync-hostfakesplit-mod=altorder=1` switches `hostfakesplit` to alternate segment ordering. `altorder=1` sends the whole request with faked host sequentally, then real host segment.
### Sequence numbers overlap
`seqovl` adds to one of the original segment `seqovl` bytes to the beginning and decreases sequence number. For `split` - to the first segment, for `disorder` - to the beginning of the penultimate segment sent (second in the original sequence).
@@ -305,6 +453,21 @@ All unix OS except Solaris preserve last received data. This is not the case for
Disorder requires `seqovl` to be less than split position. Otherwise `seqovl` is not possible and will be cancelled.
Method allows to avoid separate fakes. Fakes and real data are mixed.
### IP_ID assignment
Some DPIs check ipv4 ip_id value. OS normally increment ip_id value every packet. Some anti-DPI software may send fakes or tcp segments with the same ip_id as original causing block trigger.
Sequental ip_id will be broken in case of sending fakes or additional tcp segments because OS knows nothing about them. But still there are options how to assignt ip_id to generated packets.
`ip-id` parameter sets ip_id assignment scheme for a desync profile :
* `seq` (default) : increment ip_id for every next packet. in `multidisorder` case increase ip_id for the number of tcp segments then decrease by 1 every packet.
* `seqgroup` : same as `seq` but send fake replacements with the same ip_id as original parts. related only to fake tcp segments with the same size and same sequence as originals.
* `rnd` : assign random ip_id
* `zero` : always set zero. Linux and BSD will send zero, Windows will replace zero with it's own counter.
ipv6 header lacks ip_id field, `ip-id` parameter ignored for ipv6.
### ipv6 specific modes
`hopbyhop`, `destopt` and `ipfrag1` desync modes (they're not the same as `hopbyhop` fooling !) are ipv6 only. One `hop-by-hop`,
@@ -318,13 +481,51 @@ For example, `hopbyhop,multisplit` means split original tcp packet into several
With `hopbyhop,ipfrag2` header sequence will be : `ipv6,hop-by-hop,fragment,tcp/udp`.
`ipfrag1` mode may not always work without special preparations. See "IP Fragmentation" notices.
### Original modding
Parameters `--orig-ttl` and `--orig-ttl6` allow to set TTL on original packets.
All further packet manipulations, e.g. segmentation, take modded original as data source and inherit modded TTL.
`--orig-autottl` and `--orig-autottl6` work the same way as `dpi-desync-autottl`, but on original packets.
Delta should have unary `+` sign to produce TTL longer than guessed hop count. Otherwise nothing will reach the server.
Example : `--orig-autottl=+5:3-64`.
`--orig-mod-start` and `--orig-mod-cutoff` specify start and end conditions for original modding. The work the same way as
`--dpi-desync-start` and `--dpi-desync-cutoff`.
This function can be useful when DPI hunts for fakes and blocks suspicious connections.
DPI can compute TTL difference between packets and fire block trigger if it exceedes some threshold.
### Duplicates
Duplicates are copies of original packets which are sent before them. Duplicates are enabled by `--dup=N`, where N is dup count.
`--dup-replace` disables sending of original.
Dups are sent only when original would also be sent without reconstruction.
For example, if TCP segmentation happens, original is actually dropped and is being replaced by artificially constructed new packets.
Dups are not sent in this case.
All dup fooling modes are available : `--dup-ttl`. `--dup-ttl6`, `--dup-fooling`.
You decide whether these packets need to reach the server and in what form, according to the intended strategy.
`--dup-autottl` and `--dup-autottl6` work the same way as `dpi-desync-autottl`.
Delta can be preceeded by unary `+` or `-` sign.
Example : `--dup-autottl=-2:3-64`.
`--dup-start` and `--dup-cutoff` specify start and end conditions for dupping. The work the same way as
`--dpi-desync-start` and `--dpi-desync-cutoff`.
This function can help if DPI compares some characteristics of fake and original packets and block connection if they differ some way.
Fooled duplicates can convince DPI that the whole session has an anomaly.
For example, all connection is protected by MD5 signature, not individual packets.
### Server reply reaction
There are DPIs that analyze responses from the server, particularly the certificate from the ServerHello that contain domain name(s). The ClientHello delivery confirmation is an ACK packet from the server with ACK sequence number corresponding to the length of the ClientHello+1.
In the disorder variant, a selective acknowledgement (SACK) usually arrives first, then a full ACK.
If, instead of ACK or SACK, there is an RST packet with minimal delay, DPI cuts you off at the request stage.
If the RST is after a full ACK after a delay of about ping to the server, then probably DPI acts on the server response. The DPI may be satisfied with good ClientHello and stop monitoring the TCP session without checking ServerHello. Then you were lucky. 'fake' option could work.
If it does not stop monitoring and persistently checks the ServerHello, --wssize parameter may help (see [CONNTRACK](#conntrack)).
If it does not stop monitoring and persistently checks the ServerHello, `--wssize` parameter may help (see [CONNTRACK](#conntrack)).
Otherwise it is hardly possible to overcome this without the help of the server.
The best solution is to enable TLS 1.3 support on the server. TLS 1.3 sends the server certificate in encrypted form.
This is recommendation to all admins of blocked sites. Enable TLS 1.3. You will give more opportunities to overcome DPI.
@@ -339,12 +540,26 @@ Without extra parameter payload is 16 zero bytes.
`--dpi-desync` takes up to 3 comma separated modes.
* 0 phase modes work during the connection establishement : `synack`, `syndata` `--wsize`, `--wssize`. [hostlist](((#multiple-strategies))) filters are not applicable.
* 0 phase modes work during the connection establishement : `synack`, `syndata` `--wsize`, `--wssize`. [hostlist](#multiple-strategies) filters are applicable only if [`--ipcache-hostname`](#ip-cache) is enabled.
* In the 1st phase fakes are sent before original data : `fake`, `rst`, `rstack`.
* In the 2nd phase original data is sent in a modified way (for example `fakedsplit` or `ipfrag2`).
Modes must be specified in phase ascending order.
### IP cache
`ipcache` is the structure in the process memory that stores some information by IP address and interface name key.
This information can be used as missing data. Currently it's used in the following cases :
1. IP,interface => hop count . This is used to apply autottl at 0 phase since the first session packet. If the record is absent autottl will not be applied immediately. Second time it will be applied immediately using cached hop count.
2. IP => hostname . Hostname is cached to be used in 0 phase strategies. Mode is disabled by default and can be enabled by `ipcache-hostname` parameter.
This tech is experimental. There's no one-to-one correspondence between IP and domain name. Multiple domains can resolve to the same IP.
If collision happens hostname is replaced. On CDNs a domain can resolve to different IPs over time. `--ipcache-lifetime` limits how long cached record is valid. It's 2 hours by default.
Be prepared for unexpected results that can be explained only by reading debug logs.
SIGUSR2 forces process to output it's ipcache to stdout.
### CONNTRACK
nfqws is equipped with minimalistic connection tracking system (conntrack)
@@ -373,7 +588,7 @@ That's why conntrack is required to know when to stop applying low window size.
If you do not stop and set the low wssize all the time, the speed will drop catastrophically.
Linux can overcome this using connbytes filter but other OS may not include similar filter.
In http(s) case wssize stops after the first http request or TLS ClientHello.
In http(s) case wssize stops after the first http request or TLS ClientHello unless `--wssize-forced-cutoff=0` is specified.
If you deal with a non-http(s) protocol you need `--wssize-cutoff`. It sets the threshold where wssize stops.
@@ -381,6 +596,7 @@ Threshold can be prefixed with 'n' (packet number starting from 1), 'd' (data pa
's' (relative sequence number - sent by client bytes + 1).
If a http request or TLS ClientHello packet is detected wssize stops immediately ignoring wssize-cutoff option.
This action is called "forced wssize cutoff" and can disabled using `--wssize-forced-cutoff=0`.
If your protocol is prone to long inactivity, you should increase ESTABLISHED phase timeout using `--ctrack-timeouts`.
@@ -434,16 +650,16 @@ There is special support for all tcp split options for multi segment TLS. Split
### UDP support
UDP attacks are limited. Its not possible to fragment UDP on transport level, only on network (ip) level.
Only desync modes `fake`,`hopbyhop`,`destopt`,`ipfrag1` and `ipfrag2` are applicable.
`fake`,`hopbyhop`,`destopt` can be used in combo with `ipfrag2`.
`fake` can be used in combo with `udplen` and `tamper`.
Only desync modes `fake`,`fakeknown`,`hopbyhop`,`destopt`,`ipfrag1`,`ipfrag2`,`udplen` and `tamper` are applicable.
`fake`,`fakeknown`,`hopbyhop`,`destopt`,`ipfrag1` are 1st phase modes, others - 2nd phase.
As always it's possible to combine one mode from 1st phase with one mode from 2nd phase but not possible to mix same phase modes.
`udplen` increases udp payload size by `--dpi-desync-udplen-increment` bytes. Padding is filled with zeroes by default but can be overriden with a pattern.
This option can resist DPIs that track outgoing UDP packet sizes.
Requires that application protocol does not depend on udp payload size.
QUIC initial packets are recognized. Decryption and hostname extraction is supported so `--hostlist` parameter will work.
Wireguard handshake initiation and DHT packets are also recognized.
Wireguard handshake initiation, DHT, STUN and [Discord Voice IP Discovery](https://discord.com/developers/docs/topics/voice-connections#ip-discovery) packets are also recognized.
For other protocols desync use `--dpi-desync-any-protocol`.
Conntrack supports udp. `--dpi-desync-cutoff` will work. UDP conntrack timeout can be set in the 4th parameter of `--ctrack-timeouts`.
@@ -539,6 +755,30 @@ This way you may never unblock all resources and only confuse yourself.
IMPORTANT : user-mode ipset implementation was not designed as a kernel version replacement. Kernel version is much more effective.
It's for the systems that lack ipset support : Windows and Linux without nftables and ipset kernel modules (Android, for example).
### WIFI filtering
Wifi interface name is not related to connected SSID.
It's possible to connect interface to different SSIDs.
They may require different strategies. How to solve this problem ?
You can run and stop nfqws instances manually. But you can also automate this.
Windows version `winws` has global filter `--ssid-filter`.
It connects or disconnects `winws` depending on connected SSIDs.
Routing is not take into account. This approach is possible because windivert can have multiple handlers with intersecting filter.
If SSID changes one `winws` connects and others disconnect.
`winws` solution is hard to implement in Linux because one nfqueue can have only one handler and it's impossible to pass same traffic to multiple queues.
One must connect when others have already disconnected.
Instead, `nfqws` has per-profile `--filter-ssid` parameter. Like `--ssid-filter` it takes comma separated SSID list.
`nfqws` maintains ifname->SSID list which is updated not faster than once a second.
When a packet comes incoming or outgoing interface name is matched to the SSID and then used in profile selection algorithm.
SSID info is taken the same way as `iw dev <ifname> info` does (nl80211).
Unfortunately it's broken since kernel 5.19 and still unfixed in 6.14.
In the latter case `iwgetid` way is used (wireless extensions).
Wireless extensions are deprecated. Some kernels can be built without wext support.
Before using `--filter-ssid` check that any of the mentioned commands can return SSID.
### Virtual machines
Most of nfqws packet magic does not work from VMs powered by virtualbox and vmware when network is NATed.
@@ -547,6 +787,9 @@ Set up bridge networking.
### IPTABLES for nfqws
> [!CAUTION]
> Starting from Linux kernel 6.17 there's CONFIG_NETFILTER_XTABLES_LEGACY parameter which is not set by default. Many distributions will likely not turn it on making iptables-legacy non working. This is part of iptables deprecation. However iptables-nft still works because their backend is based on nftables.
This is the common way to redirect some traffic to nfqws :
```
@@ -631,6 +874,31 @@ In `iptables` flow offloading is controlled by openwrt proprietary extension `FL
Flow offloading does not interfere with **tpws** and `OUTPUT` traffic. It only breaks nfqws that fools `FORWARD` traffic.
### Server side fooling
It's also possible.
nfqws is intended for client side attacks. That's why it recognizes direct and reply traffic based on role in connection establishement.
If it sees SYN then source IP is client IP. If it sees SYN,ACK then source ip is server IP.
For UDP client address is considered as source IP of the first seen packet of src_ip,src_port,dst_ip,dst_port tuple.
This does not work correctly on the server side. Client traffic is reply traffic, server traffic is direct traffic.
`--wsize` works in any case. It can be used on both client and server.
Other techs work only if nfqws treats traffic as direct traffic.
To apply them to server originated traffic disable conntrack by `--ctrack-disable` parameter.
If a packet is not found in conntrack it's treated as direct and techs like `multidisorder` will be applied.
Most of the protocols will not be recognized because protocol recognition system only reacts to client packets.
To make things working use `--dpi-desync-any-protocol` with connbytes or packet payload limiter.
start/cutoff are unavailable because they are conntrack based.
`--synack-split` removes standard SYN,ACK packet and replaces it with one SYN packet, SYN then ACK separate packets or ACK then SYN separate packets.
Client sends SYN,ACK in reply which usually only server does.
This makes some DPI's to treat connection establishement roles wrong. They stop to block.
See [split handshake](https://nmap.org/misc/split-handshake.pdf).
On server side traffic should be redirected to nfqws using source port numbers and original connbytes direction.
## tpws
@@ -642,6 +910,7 @@ tpws is transparent proxy.
--debug=0|1|2|syslog|@<filename> ; 1 and 2 means log to console and set debug level. for other targets use --debug-level.
--debug-level=0|1|2 ; specify debug level for syslog and @<filename>
--dry-run ; verify parameters and exit with code 0 if successful
--version ; print version and exit
--bind-addr=<v4_addr>|<v6_addr> ; for v6 link locals append %interface_name : fe80::1%br-lan
--bind-iface4=<interface_name> ; bind to the first ipv4 addr of interface
--bind-iface6=<interface_name> ; bind to the first ipv6 addr of interface
@@ -666,6 +935,8 @@ tpws is transparent proxy.
--local-tcp-user-timeout=<seconds> ; set tcp user timeout for local leg (default : 10, 0 = system default)
--remote-tcp-user-timeout=<seconds> ; set tcp user timeout for remote leg (default : 20, 0 = system default)
--fix-seg=<int> ; recover failed TCP segmentation at the cost of slowdown. wait up to N msec.
--ipcache-lifetime=<int> ; time in seconds to keep cached domain name (default 7200). 0 = no expiration
--ipcache-hostname=[0|1] ; 1 or no argument enables ip->hostname caching
--no-resolve ; disable socks5 remote dns
--resolver-threads=<int> ; number of resolver worker threads
--maxconn=<max_connections> ; max number of local legs
@@ -683,9 +954,9 @@ tpws is transparent proxy.
--ipset-exclude=<filename> ; ipset exclude filter (one ip/CIDR per line, ipv4 and ipv6 accepted, gzip supported, multiple ipsets allowed)
--ipset-exclude-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=<filename> ; only act on hosts in the list (one host per line, subdomains auto apply if not prefixed with '^', gzip supported, multiple hostlists allowed)
--hostlist-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=<filename> ; do not act on hosts in the list (one host per line, subdomains auto apply if not prefixed with '^', gzip supported, multiple hostlists allowed)
--hostlist-exclude-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)
@@ -716,7 +987,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[:gid1,gid2,...] ; drop root privs
```
### TCP segmentation in tpws
@@ -750,7 +1021,7 @@ If you're attempting to split massive transmission with `--split-any-protocol` o
`--mss` sets TCP_MAXSEG socket option. Client sets this value in MSS TCP option in the SYN packet.
Server replies with it's own MSS in SYN,ACK packet. Usually servers lower their packet sizes but they still don't fit to supplied MSS. The greater MSS client sets the bigger server's packets will be.
If it's enough to split TLS 1.2 ServerHello, it may fool DPI that checks certificate domain name.
This scheme may significantly lower speed. Hostlist filter is possible only in socks mode if client uses remote resolving (firefox `network.proxy.socks_remote_dns`).
This scheme may significantly lower speed. Hostlist filter is possible only in socks mode if client uses remote resolving (firefox `network.proxy.socks_remote_dns`) or if `ipcache-hostname` is enabled.
`--mss` is not required for TLS1.3. If TLS1.3 is negotiable then MSS make things only worse. Use only if nothing better is available. Works only in Linux, not BSD or MacOS.
### Other tamper options
@@ -963,9 +1234,11 @@ If `MODE_FILTER=hostlist` all present lists are passed to **nfqws** or **tpws**.
If all include lists are empty it works like no include lists exist at all.
If you need "all except" mode you dont have to delete zapret-hosts-users.txt. Just make it empty.
Subdomains auto apply. For example, "ru" in the list affects "*.ru" .
Subdomains auto apply. For example, "ru" in the list affects "\*.ru" .
`^` prefix symbol disables subdomain match.
**tpws** and **nfqws** automatically reload lists if their modification 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 !
@@ -1049,6 +1322,23 @@ Don't use `<HOSTLIST>` in highly specialized profiles. Use your own filter or ho
`<HOSTLIST_NOAUTO>` marker uses standard autohostlist as usual hostlist thus disabling auto additions in this profile.
If any other profile adds something this profile accepts the change automatically.
Change loop prevention mark bit
`DESYNC_MARK=0x40000000`
Change postnat scheme mark bit
`DESYNC_MARK_POSTNAT=0x20000000`
If uncommented pass to zapret only packets marked with this bit
`#FILTER_MARK=0x10000000`
Bit must be set in your own rules.
* iptables - in mangle PREROUTING and mangle OUTPUT before zapret rules (iptables -I _after_ zapret rules application).
* nftables - in output and prerouting hooks with priority -102 or lower.
Mark criterias can be any. For example, source IP or source interface name.
**tpws** socks proxy mode switch
@@ -1229,6 +1519,10 @@ With other values or if the parameter is commented out, the rules will not be ap
This is useful if you have a firewall management system, in the settings of which you should tie the rules.
Not applicable to `OpenWRT` if used with `firewall3+iptables`.
`FILTER_TTL_EXPIRED_ICMP=1` blocks icmp time exceeded messages in response to connections handled by nfqws.
Linux closes socket if it receives this icmp in response to SYN packet. Similar mechanism exists for datagram sockets.
It's better to disable this if you do not expect problems caused by icmp.
The following settings are not relevant for openwrt :
If your system works as a router, then you need to enter the names of the internal and external interfaces:
@@ -1410,12 +1704,8 @@ If this is the case then run another script in background and add some delay the
Are welcome here :
<img src=https://cdn-icons-png.flaticon.com/16/14446/14446252.png alt="USDT" style="vertical-align: middle;"/> USDT
```
0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E
```
USDT `0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E`
<img src=https://cdn-icons-png.flaticon.com/16/5968/5968260.png alt="USDT" style="vertical-align: middle;"/> BTC
```
bc1qhqew3mrvp47uk2vevt5sctp7p2x9m7m5kkchve
```
BTC `bc1qhqew3mrvp47uk2vevt5sctp7p2x9m7m5kkchve`
ETH `0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E`

File diff suppressed because it is too large Load Diff

View File

@@ -24,17 +24,15 @@ Tor поддерживает "из коробки" режим transparent proxy.
Устанавливать их нужно с опцией opkg --force-overwrite, поскольку они перепишут ssh клиент от dropbear.
После установки пакетов расслабим неоправданно жестокие права : chmod 755 /etc/ssh.
Следует создать пользователя, под которым будем крутить ssh client. Допустим, это будет 'proxy'.
Сначала установить пакет shadow-useradd.
Сначала установить пакеты shadow-useradd и shadow-su.
------------------
useradd -d /home/proxy proxy
useradd -s /bin/false -d /home/proxy proxy
mkdir -p /home/proxy
chown proxy:proxy /home/proxy
------------------
Openssh ловит разные глюки, если у него нет доступа к /dev/tty.
Добавим в /etc/rc.local строчку : "chmod 666 /dev/tty"
Сгенерируем для него ключ RSA для доступа к ssh серверу.
Сгенерируем ключ RSA для доступа к ssh серверу.
------------------
su proxy
su -s /bin/ash proxy
cd
mkdir -m 700 .ssh
cd .ssh

View File

@@ -7,7 +7,7 @@ tpws is static binary. It doesn't need a distribution.
Install `WSL` : `dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all`
Copy `binaries/x86_64/tpws_wsl.tgz` to the target system.
From release copy `binaries/linux-x86_64/tpws_wsl.tgz` to the target system.
Run : `wsl --import tpws "%USERPROFILE%\tpws" tpws_wsl.tgz`
Run tpws : `wsl -d tpws --exec /tpws --uid=1 --no-resolve --socks --bind-addr=127.0.0.1 --port=1080 <fooling_options>`
@@ -16,7 +16,7 @@ Configure socks as `127.0.0.1:1080` in a browser or another program.
Cleanup : `wsl --unregister tpws`
Tested in windows 10 build 19041 (20.04).
Tested in windows 10 build 19041 (20.04) with WSL1.
`--oob` , `--mss` and `--disorder` do not work.
RST detection in autohostlist scheme may not work.
@@ -47,7 +47,9 @@ Task of `iptables` is done inside `winws` through `windivert` filters. `Windiver
--wf-l3=ipv4|ipv6 ; L3 protocol filter. multiple comma separated values allowed.
--wf-tcp=[~]port1[-port2] ; TCP port filter. ~ means negation. multiple comma separated values allowed.
--wf-udp=[~]port1[-port2] ; UDP port filter. ~ means negation. multiple comma separated values allowed.
--wf-raw=<filter>|@<filename> ; raw windivert filter string or filename
--wf-raw-part=<filter>|@<filename> ; partial raw windivert filter string or filename
--wf-filter-lan=0|1 ; add excluding filter for non-global IP (default : 1)
--wf-raw=<filter>|@<filename> ; full raw windivert filter string or filename. replaces --wf-tcp,--wf-udp,--wf-raw-part
--wf-save=<filename> ; save windivert filter string to a file and exit
--ssid-filter=ssid1[,ssid2,ssid3,...] ; enable winws only if any of specified wifi SSIDs connected
--nlm-filter=net1[,net2,net3,...] ; enable winws only if any of specified NLM network is connected. names and GUIDs are accepted.
@@ -60,6 +62,12 @@ Interface indexes can be discovered using this command : `netsh int ip show int`
If you can't find index this way use `winws --debug` to see index there. Subinterface index is almost always 0 and you can omit it.
`--wf-raw-part` specifies partial windivert filter. Multiple filter parts are supported. They can also be combined with `--wf-tcp`,`--wf-udp`.
`--wf-raw` specifies full windivert filter that replaces `--wf-tcp`,`--wf-udp`,`--wf-raw-part`.
Kernel filtering with windivert language is much more effective than passing massive amount of traffic to winws. Use it if possible to save CPU resources.
Multiple `winws` processes are allowed. However, it's discouraged to intersect their filters.
`--ssid-filter` allows to enable `winws` only if specified wifi networks are connected. `winws` auto detects SSID appearance and disappearance.
@@ -83,7 +91,7 @@ You must choose to install `curl`. To compile from sources install `gcc-core`,`m
Make from directory `nfq` using `make cygwin64` or `make cygwin32` for 64 and 32 bit versions.
`winws` requires `cygwin1.dll`, `windivert.dll`, `windivert64.sys` or `windivert32.sys`.
You can take them from `binaries/win64` or `binaries/win32`.
You can take them from `binaries/windows-x86_64` or `binaries/windows-x86`.
There's no `arm64` signed `windivert` driver and no `cygwin`.
But it's possible to use unsigned driver version in test mode and user mode components with x64 emulation.
@@ -128,19 +136,6 @@ If you want to run `winws` from `cygwin` delete, rename or move `cygwin1.dll`.
To simplify things it's advised to use `zapret-win-bundle`.
### auto start
To start `winws` with windows use windows task scheduler. There are `task_*.cmd` batch files in `binaries/win64/zapret-winws`.
They create, remove, start and stop scheduled task `winws1`. They must be run as administrator.
Edit `task_create.cmd` and write your `winws` parameters to `%WINWS1%` variable. If you need multiple `winws` instances
clone the code in all cmd files to support multiple tasks `winws1,winws2,winws3,...`.
Tasks can also be controlled from GUI `taskschd.msc`.
Also you can use windows services the same way with `service_*.cmd`.
### zapret-win-bundle
To make your life easier there's ready to use [bundle](https://github.com/bol-van/zapret-win-bundle) with `cygwin`,`blockcheck` and `winws`.
@@ -166,3 +161,21 @@ unix2dos winws.log
`winws.log` will be in `cygwin/home/<username>`. `unix2dos` helps with `windows 7` notepad. It's not necessary in `Windows 10` and later.
Because 32-bit systems are rare nowadays `zapret-win-bundle` exists only for `Windows x64/arm64`.
### auto start
To start `winws` with windows use windows task scheduler. There are `task_*.cmd` batch files in `binaries/windows-x86-64/zapret-winws`.
They create, remove, start and stop scheduled task `winws1`. They must be run as administrator.
Edit `task_create.cmd` and write your `winws` parameters to `%WINWS1%` variable. If you need multiple `winws` instances
clone the code in all cmd files to support multiple tasks `winws1,winws2,winws3,...`.
Tasks can also be controlled from GUI `taskschd.msc`.
Also you can use windows services the same way with `service_*.cmd`.
### Windows Server
winws is linked against wlanapi.dll which is absent by default.
To solve this problem run power shell as administrator and execute command `Install-WindowsFeature -Name Wireless-Networking`.
Then reboot the system.

View File

@@ -12,7 +12,7 @@ tpws в режиме socks можно запускать под более-ме
Установить WSL :
`dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all`
Скопировать на целевую систему `binaries/x86_64/tpws_wsl.tgz`.
Из релиза скопировать на целевую систему `binaries/linux-x86_64/tpws_wsl.tgz`.
Выполнить :
`wsl --import tpws "%USERPROFILE%\tpws" tpws_wsl.tgz`
@@ -24,8 +24,12 @@ tpws в режиме socks можно запускать под более-ме
Удаление : `wsl --unregister tpws`
> [!NOTE]
> Проверено на windows 10 build 19041 (20.04).
> Проверено на windows 10 build 19041 (20.04) под WSL1. На WSL2 эти команды могут не сработать.
Если у вас есть WSL2, значит у вас есть работающая виртуалка с linux.
Если вы умеете с ней обращаться, tpws на ней запустить возможно без всяких проблем.
Возможные проблемы:
- Не работают функции `--oob` и `--mss` из-за ограничений реализации WSL.
@@ -44,7 +48,7 @@ tpws в режиме socks можно запускать под более-ме
Это вариант пакетного фильтра nfqws для Windows, построенный на базе windivert.
Все функции работоспособны, однако функционал ipset в ядре отсутствует. Он реализован в user mode. Фильтры по большому количеству IP адресов невозможны.
Работа с проходящим трафиком, например в случае "расшаривания" соединения, не проверялась и не гарантируется.
Работа с проходящим трафиком, например в случае "расшаривания" соединения, невозможна.
Для работы с windivert требуются права администратора.
Специфические для unix параметры, такие как `--uid`, `--user` и тд, исключены. Все остальные параметры аналогичны nfqws и dvtws.
@@ -63,15 +67,17 @@ secure boot могут быть проблемы из-за подписи дра
Чтобы не писать сложные фильтры вручную, предусмотрены различные упрощенные варианты автоматического построения фильтров.
```
--wf-iface=<int>[.<int>] ; числовые индексы интерфейса и суб-интерфейса
--wf-l3=ipv4|ipv6 ; фильтр L3 протоколов. по умолчанию включены ipv4 и ipv6.
--wf-tcp=[~]port1[-port2] ; фильтр портов для tcp. ~ означает отрицание
--wf-udp=[~]port1[-port2] ; фильтр портов для udp. ~ означает отрицание
--wf-raw=<filter>|@<filename> ; задать напрямую фильтр windivert из параметра или из файла. имени файла предшествует символ @.
--wf-save=<filename> ; сохранить сконструированный фильтр windivert в файл для последующей правки вручную
--wf-iface=<int>[.<int>] ; числовые индексы интерфейса и суб-интерфейса
--wf-l3=ipv4|ipv6 ; фильтр L3 протоколов. по умолчанию включены ipv4 и ipv6.
--wf-tcp=[~]port1[-port2] ; фильтр портов для tcp. ~ означает отрицание
--wf-udp=[~]port1[-port2] ; фильтр портов для udp. ~ означает отрицание
--wf-raw-part=<filter>|@<filename> ; частичный windivert фильтр из параметра или из файла. имени файла предшествует символ @. может быть множество частей. сочетается с --wf-tcp,--wf-udp.
--wf-filter-lan=0|1 ; отфильтровывать адреса назначения, не являющиеся глобальными inet адресами ipv4 или ipv6. по умолчанию - 1.
--wf-raw=<filter>|@<filename> ; полный windivert фильтр из параметра или из файла. имени файла предшествует символ @. замещает --wf-raw-part,--wf-tcp,--wf-udp.
--wf-save=<filename> ; сохранить сконструированный фильтр windivert в файл для последующей правки вручную
--ssid-filter=ssid1[,ssid2,ssid3,...] ; включать winws только когда подключена любая из указанных wifi сетей
--nlm-filter=net1[,net2,net3,...] ; включать winws только когда подключена любая из указанных сетей NLM
--nlm-list[=all] ; вывести список сетей NLM. по умолчанию только подключенных, all - всех.
--nlm-filter=net1[,net2,net3,...] ; включать winws только когда подключена любая из указанных сетей NLM
--nlm-list[=all] ; вывести список сетей NLM. по умолчанию только подключенных, all - всех.
```
Параметры `--wf-l3`, `--wf-tcp`, `--wf-udp` могут брать несколько значений через запятую.
@@ -80,11 +86,19 @@ secure boot могут быть проблемы из-за подписи дра
Некоторых типы соединений там не увидеть. В этом случае запускайте **winws** с параметром `--debug` и смотрите IfIdx там.
SubInterface используется windivert, но практически всегда **0**, его можно не указывать. Вероятно, он нужен в редких случаях.
Конструктор фильтров автоматически включает входящие tcp пакеты с tcp synack и tcp rst для корректной работы функций
Конструктор стандартных фильтров автоматически включает входящие tcp пакеты с tcp synack и tcp rst для корректной работы функций
autottl и autohostlist. При включении autohostlist так же перенаправляются пакеты данных с http redirect с кодами 302 и 307.
Всегда добавляется фильтр на исключение не-интернет адресов ipv4 и ipv6.
Для сложных нестандартных сценариев могут потребоваться свои фильтры. Логично будет начать со стандартного шаблона,
сохраненного через `--wf-save`. Нужно править файл и подсовывать его в параметре `--wf-raw`. Максимальный размер фильтра - **8 Kb**.
Если не указаное иное, добавляется фильтр на исключение не-интернет адресов ipv4 и ipv6.
Для сложных нестандартных сценариев могут потребоваться свои фильтры. Полный фильтр --wf-raw замещает все остальное.
Частичные фильтры `--wf-raw-part` совместимы друг с другом и `--wf-tcp` и `--wf-udp`. Они позволяют исключить написание
громоздких полных фильтров, сосредоточившись лишь на добавлении какого-то особенного пейлоада.
`--wf-save` позволяет записать итоговый windivert фильтр в файл. Максимальный размер фильтра - **16 Kb**.
Фильтрация windivert производится в ядре. Это несравнимо легче по ресурсам, чем перенаправлять пакеты в пространство user mode,
чтобы winws принимал решение. Поэтому пользуйтесь по максимуму возможностями windivert.
Например, если вам нужно дурить wireguard на все порты, вам придется перенаправить все порты на winws. Или же написать windivert фильтр, который отсечет wireguard по содержимому пакета.
Разница в нагрузке на процессор колоссальна. В первом случае - до 100% одного ядра cpu в зависимости от обьема исходящего udp трафика (привет, торрент и uTP), во втором - близко к 0.
Кроме нагрузки на процессор еще можете порезать себе скорость, тк одно ядро не будет справляться с обработкой вашего гигабитного интернета. А на старых ноутах еще и получите самолетный вой системы охлаждения, приводящий к ее износу.
Можно запускать несколько процессов **winws** с разными стратегиями. Однако, не следует делать пересекающиеся фильтры.
@@ -125,7 +139,7 @@ network locations в win10/11. Кое-что есть в **powershell**.
Существует неочевидный момент, каcаемый запуска **winws** из cygwin shell\`а. Если в директории, где находится winws, находится
копия `cygwin1.dll`, **winws** не запустится.
Если нужен запуск под cygwin, то следует удалить или переместить `cygwin1.dll` из `binaries/win64`. Это нужно для работы blockcheck.
Если нужен запуск под cygwin, то следует удалить или переместить `cygwin1.dll` из `binaries/windows-x86_64`. Это нужно для работы blockcheck.
Из cygwin шелла можно посылать winws сигналы через `kill` точно так же, как в `*nix`.
Как получить совместимый с windows 7 и winws cygwin :
@@ -203,22 +217,6 @@ _cygwin_ для обычной работы **winws** не нужен.
Однако, хотя такой способ и работает, использование **winws** сильно облегчает [zapret-win-bundle](https://github.com/bol-van/zapret-win-bundle).
Там нет проблемы с `cygwin.dll`.
## Автозапуск winws
Для запуска **winws** вместе с windows есть 2 варианта. Планировщик задач или службы windows.
Можно создавать задачи и управлять ими через консольную программу schtasks.
В директории `binaries/win64/winws` подготовлены файлы `task_*.cmd` .
В них реализовано создание, удаление, старт и стоп одной копии процесса winws с параметрами из переменной `%WINWS1%`.
Исправьте параметры на нужную вам стратегию. Если для разных фильтров применяется разная стратегия, размножьте код
для задач _winws1_,_winws2_,_winws3_,_..._
Аналогично настраивается вариант запуска через службы windows. Смотрите `service_*.cmd`.
Все батники требуется запускать от имени администратора.
Управлять задачами можно так же из графической программы управления планировщиком `taskschd.msc`
## Zapret-win-bundle
Можно не возиться с _cygwin_, а взять готовый пакет, включающий в себя _cygwin_ и _blockcheck_ : https://github.com/bol-van/zapret-win-bundle
@@ -257,3 +255,25 @@ _zapret-winws_ - это отдельный комплект для повсед
> [!CAUTION]
> Поскольку 32-битные windows мало востребованы, _zapret-win-bundle_ существует только в варианте для windows _x64/arm64_.
## Автозапуск winws
Для запуска **winws** вместе с windows есть 2 варианта. Планировщик задач или службы windows.
Можно создавать задачи и управлять ими через консольную программу schtasks.
В директории `binaries/windows-x86_64/winws` подготовлены файлы `task_*.cmd` .
В них реализовано создание, удаление, старт и стоп одной копии процесса winws с параметрами из переменной `%WINWS1%`.
Исправьте параметры на нужную вам стратегию. Если для разных фильтров применяется разная стратегия, размножьте код
для задач _winws1_,_winws2_,_winws3_,_..._
Аналогично настраивается вариант запуска через службы windows. Смотрите `service_*.cmd`.
Все батники требуется запускать от имени администратора.
Управлять задачами можно так же из графической программы управления планировщиком `taskschd.msc`
## Особенности Windows Server
winws слинкован с wlanapi.dll, который по умолчанию не установлен в windows server.
Для решения этой проблемы запустите power shell под администратором и выполните команду `Install-WindowsFeature -Name Wireless-Networking`.
После чего перезагрузите систему.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
files/fake/stun.bin Normal file

Binary file not shown.

View File

@@ -1,4 +1,5 @@
# this custom script runs desync to DHT packets with udp payload length 101..399 , without ipset/hostlist filtering
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
# can override in config :
NFQWS_OPT_DESYNC_DHT="${NFQWS_OPT_DESYNC_DHT:---dpi-desync=tamper}"
@@ -10,20 +11,20 @@ zapret_custom_daemons()
{
# $1 - 1 - add, 0 - stop
local opt="--qnum=$QNUM_DHT4ALL $NFQWS_OPT_DESYNC_DHT"
local opt="--qnum=$QNUM_DHT4ALL $NFQWS_OPT_DESYNC_DHT"
do_nfqws $1 $DNUM_DHT4ALL "$opt"
}
zapret_custom_firewall()
{
# $1 - 1 - run, 0 - stop
local f uf4 uf6
local first_packet_only="$ipt_connbytes 1:1"
local f uf4 uf6
local first_packet_only="$ipt_connbytes 1:1"
f='-p udp -m length --length 109:407 -m u32 --u32'
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
fw_nfqws_post $1 "$f $uf4 $first_packet_only" "$f $uf6 $first_packet_only" $QNUM_DHT4ALL
}
zapret_custom_firewall_nft()
{
@@ -32,6 +33,6 @@ zapret_custom_firewall_nft()
local f
local first_packet_only="$nft_connbytes 1"
f="meta length 109-407 meta l4proto udp @th,64,16 0x6431"
f="meta length 109-407 meta l4proto udp @ih,0,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

@@ -0,0 +1,35 @@
# this custom script runs desync to all discord media packets
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
# can override in config :
NFQWS_OPT_DESYNC_DISCORD_MEDIA="${NFQWS_OPT_DESYNC_DISCORD_MEDIA:---dpi-desync=fake --dpi-desync-repeats=2}"
DISCORD_MEDIA_PORT_RANGE="${DISCORD_MEDIA_PORT_RANGE:-50000-50099}"
alloc_dnum DNUM_DISCORD_MEDIA
alloc_qnum QNUM_DISCORD_MEDIA
zapret_custom_daemons()
{
# $1 - 1 - add, 0 - stop
local opt="--qnum=$QNUM_DISCORD_MEDIA $NFQWS_OPT_DESYNC_DISCORD_MEDIA"
do_nfqws $1 $DNUM_DISCORD_MEDIA "$opt"
}
zapret_custom_firewall()
{
# $1 - 1 - run, 0 - stop
local DISABLE_IPV6=1
local port_range=$(replace_char - : $DISCORD_MEDIA_PORT_RANGE)
local f="-p udp --dport $port_range -m u32 --u32"
# this is simplified test to skip writing monstrous rule. instead of checking 64 bytes for zeroes only check 2 dwords for zero
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=0x52&&0>>22&0x3C@8=0x00010046&&0>>22&0x3C@16=0&&0>>22&0x3C@76=0" '' $QNUM_DISCORD_MEDIA
}
zapret_custom_firewall_nft()
{
# stop logic is not required
local DISABLE_IPV6=1
local f="udp dport $DISCORD_MEDIA_PORT_RANGE udp length == 82 @ih,0,32 0x00010046 @ih,64,128 0x00000000000000000000000000000000 @ih,192,128 0x00000000000000000000000000000000 @ih,320,128 0x00000000000000000000000000000000 @ih,448,128 0x00000000000000000000000000000000"
nft_fw_nfqws_post "$f" '' $QNUM_DISCORD_MEDIA
}

View File

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

View File

@@ -0,0 +1,30 @@
# this custom script runs desync to all IETF QUIC initials
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
# can override in config :
NFQWS_OPT_DESYNC_QUIC="${NFQWS_OPT_DESYNC_QUIC:---dpi-desync=fake --dpi-desync-repeats=2}"
alloc_dnum DNUM_QUIC4ALL
alloc_qnum QNUM_QUIC4ALL
zapret_custom_daemons()
{
# $1 - 1 - add, 0 - stop
local opt="--qnum=$QNUM_QUIC4ALL $NFQWS_OPT_DESYNC_QUIC"
do_nfqws $1 $DNUM_QUIC4ALL "$opt"
}
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=264:65535&&0>>22&0x3C@8>>28=0xC&&0>>22&0x3C@9=0x00000001" "$f 44>>16=264:65535&&48>>28=0xC&&49=0x00000001" $QNUM_QUIC4ALL
}
zapret_custom_firewall_nft()
{
# stop logic is not required
local f="udp length >= 264 @ih,0,4 0xC @ih,8,32 0x00000001"
nft_fw_nfqws_post "$f" "$f" $QNUM_QUIC4ALL
}

View File

@@ -0,0 +1,30 @@
# this custom script runs desync to all stun packets
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
# can override in config :
NFQWS_OPT_DESYNC_STUN="${NFQWS_OPT_DESYNC_STUN:---dpi-desync=fake --dpi-desync-repeats=2}"
alloc_dnum DNUM_STUN4ALL
alloc_qnum QNUM_STUN4ALL
zapret_custom_daemons()
{
# $1 - 1 - add, 0 - stop
local opt="--qnum=$QNUM_STUN4ALL $NFQWS_OPT_DESYNC_STUN"
do_nfqws $1 $DNUM_STUN4ALL "$opt"
}
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=28:65535&&0>>22&0x3C@12=0x2112A442&&0>>22&0x3C@8&0xC0000003=0" "$f 44>>16=28:65535&&52=0x2112A442&&48&0xC0000003=0" $QNUM_STUN4ALL
}
zapret_custom_firewall_nft()
{
# stop logic is not required
local f="udp length >= 28 @ih,32,32 0x2112A442 @ih,0,2 0 @ih,30,2 0"
nft_fw_nfqws_post "$f" "$f" $QNUM_STUN4ALL
}

View File

@@ -28,7 +28,6 @@ zapret_custom_firewall()
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
@@ -58,7 +57,7 @@ zapret_custom_firewall()
zapret_custom_firewall_nft()
{
local f4 f6 subnet
local f4 f6 subnets
[ "$DISABLE_IPV4" != 1 ] && {
make_comma_list subnets $TPWS_MY1_SUBNETS4

View File

@@ -1,7 +1,9 @@
# this custom script runs desync to all wireguard handshake initiation packets
# NOTE: this works for original wireguard and may not work for 3rd party implementations such as xray
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
# can override in config :
NFQWS_OPT_DESYNC_WG="${NFQWS_OPT_DESYNC_WG:---dpi-desync=fake}"
NFQWS_OPT_DESYNC_WG="${NFQWS_OPT_DESYNC_WG:---dpi-desync=fake --dpi-desync-repeats=2}"
alloc_dnum DNUM_WG4ALL
alloc_qnum QNUM_WG4ALL
@@ -10,7 +12,7 @@ zapret_custom_daemons()
{
# $1 - 1 - add, 0 - stop
local opt="--qnum=$QNUM_WG4ALL $NFQWS_OPT_DESYNC_WG"
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
@@ -18,13 +20,13 @@ 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
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
local f="udp length 156 @ih,0,32 0x01000000"
nft_fw_nfqws_post "$f" "$f" $QNUM_WG4ALL
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,14 @@
Цель этих фильтров - отсекать полезную нагрузку в режиме ядра, не насилуя процессор перенаправлением целого потока на winws.
Задействуются через `winws --wf-raw-part=@filename`. Может быть несколько частичных фильтров. Они могут сочетаться с --wf-tcp и --wf-udp.
Однако, язык фильтров windivert не содержит операций с битовыми полями, сдвигов и побитовой логики.
Поэтому фильтры получились более слабыми, способными передавать неправильную нагрузку.
Дофильтрация производится силами winws.
Описание языка фильтров : https://reqrypt.org/windivert-doc.html#filter_language
Пример инстанса для пробития медиапотоков в discord : `winws --wf-raw-part=@windivert_part.discord_media.txt --wf-raw-part=@windivert_part.stun.txt --filter-l7=stun,discord --dpi-desync=fake`
These filters are invoked using `winws --wf-raw-part=@filename`. Multiple filter parts are supported. They can be combined with --wf-tcp and --wf-udp.
Filters are kernel mode and save great amount of CPU.
However windivert cannot filter by bit fields, lacks shift and bitwise logic operations.
Filters are relaxed and can pass wrong payloads. Finer filtering is done by winws.

View File

@@ -0,0 +1,20 @@
outbound and ip and
udp.DstPort>=50000 and udp.DstPort<=50099 and
udp.PayloadLength=74 and
udp.Payload32[0]=0x00010046 and
udp.Payload32[2]=0 and
udp.Payload32[3]=0 and
udp.Payload32[4]=0 and
udp.Payload32[5]=0 and
udp.Payload32[6]=0 and
udp.Payload32[7]=0 and
udp.Payload32[8]=0 and
udp.Payload32[9]=0 and
udp.Payload32[10]=0 and
udp.Payload32[11]=0 and
udp.Payload32[12]=0 and
udp.Payload32[13]=0 and
udp.Payload32[14]=0 and
udp.Payload32[15]=0 and
udp.Payload32[16]=0 and
udp.Payload32[17]=0

View File

@@ -0,0 +1,4 @@
outbound and
udp.PayloadLength>=256 and
udp.Payload[0]>=0xC0 and udp.Payload[0]<0xD0 and
udp.Payload[1]=0 and udp.Payload16[1]=0 and udp.Payload[4]=1

View File

@@ -0,0 +1,3 @@
outbound and
udp.PayloadLength>=20 and
udp.Payload32[1]=0x2112A442 and udp.Payload[0]<0x40

View File

@@ -0,0 +1,3 @@
outbound and
udp.PayloadLength=148 and
udp.Payload[0]=0x01

View File

@@ -8,6 +8,68 @@ BINDIR="$EXEDIR/$BINS"
ZAPRET_BASE=${ZAPRET_BASE:-"$EXEDIR"}
. "$ZAPRET_BASE/common/base.sh"
read_elf_arch()
{
# $1 - elf file
local arch=$(dd if="$1" count=2 bs=1 skip=18 2>/dev/null | hexdump -e '2/1 "%02x"')
local bit=$(dd if="$1" count=1 bs=1 skip=4 2>/dev/null | hexdump -e '1/1 "%02x"')
echo $bit$arch
}
select_test_method()
{
local f ELF
TEST=run
# ash and dash try to execute invalid executables as a script. they interpret binary garbage with possible negative consequences
# bash and zsh do not do this
if exists bash; then
TEST=bash
elif exists zsh && [ "$UNAME" != CYGWIN ] ; then
TEST=zsh
elif [ "$UNAME" != Darwin -a "$UNAME" != CYGWIN ]; then
if exists hexdump and exists dd; then
# macos does not use ELF
TEST=elf
ELF=
ELF_ARCH=
for f in /bin/sh /system/bin/sh; do
[ -x "$f" ] && {
ELF=$f
break
}
done
[ -n "$ELF" ] && ELF_ARCH=$(read_elf_arch "$ELF")
[ -n "$ELF_ARCH" ] && return
fi
# find does not use its own shell exec
# it uses execvp(). in musl libc it does not call shell, in glibc it DOES call /bin/sh
# that's why prefer bash or zsh if present. otherwise it's our last chance
if exists find; then
TEST=find
FIND=find
elif exists busybox; then
busybox find /jGHUa3fh1A 2>/dev/null
# 127 - command not found
[ "$?" = 127 ] || {
TEST=find
FIND="busybox find"
}
fi
fi
}
disable_antivirus()
{
# $1 - dir
[ "$UNAME" = Darwin ] && find "$1" -maxdepth 1 -type f -perm +111 -exec xattr -d com.apple.quarantine {} \; 2>/dev/null
}
check_dir()
{
local dir="$BINDIR/$1"
@@ -15,23 +77,36 @@ check_dir()
local out
if [ -f "$exe" ]; then
if [ -x "$exe" ]; then
# ash and dash try to execute invalid executables as a script. they interpret binary garbage with possible negative consequences
# bash and zsh do not do this
if exists bash; then
out=$(echo 0.0.0.0 | bash -c "\"$exe"\" 2>/dev/null)
elif exists zsh; then
out=$(echo 0.0.0.0 | zsh -c "\"$exe\"" 2>/dev/null)
else
# find does not use its own shell exec
# it uses execvp(). in musl libc it does not call shell, in glibc it DOES call /bin/sh
# that's why prefer bash or zsh if present. otherwise it's our last chance
local FIND=find
if ! exists find && exists busybox; then
FIND="busybox find"
fi
out=$(echo 0.0.0.0 | $FIND "$dir" -maxdepth 1 -name ip2net -exec {} \; 2>/dev/null)
fi
[ -n "$out" ]
disable_antivirus "$dir"
case $TEST in
bash)
out=$(echo 0.0.0.0 | bash -c "\"$exe"\" 2>/dev/null)
[ -n "$out" ]
;;
zsh)
out=$(echo 0.0.0.0 | zsh -c "\"$exe\"" 2>/dev/null)
[ -n "$out" ]
;;
elf)
out=$(read_elf_arch "$exe")
[ "$ELF_ARCH" = "$out" ] && {
# exec test to verify it actually works. no illegal instruction or crash.
out=$(echo 0.0.0.0 | "$exe" 2>/dev/null)
[ -n "$out" ]
}
;;
find)
out=$(echo 0.0.0.0 | $FIND "$dir" -maxdepth 1 -name ip2net -exec {} \; 2>/dev/null)
[ -n "$out" ]
;;
run)
out=$(echo 0.0.0.0 | "$exe" 2>/dev/null)
[ -n "$out" ]
;;
*)
false
;;
esac
else
echo >&2 "$exe is not executable. set proper chmod."
return 1
@@ -52,29 +127,65 @@ ccp()
#cp -f "../$BINS/$1" "$ZAPRET_BASE/$2" && echo copying : "../$BINS/$1" =\> "$ZAPRET_BASE/$2"
}
UNAME=$(uname)
[ "$1" = getarch ] ||
if [ ! -d "$BINDIR" ] || ! dir_is_not_empty "$BINDIR" ]; then
echo "no binaries found"
case $UNAME in
Linux)
echo "you need to download release from github or build binaries from source"
echo "building from source requires debian/ubuntu packages : make gcc zlib1g-dev libcap-dev libnetfilter-queue-dev libmnl-dev libsystemd-dev"
echo "libsystemd-dev required only on systemd based systems"
echo "on distributions with other package manager find dev package analogs"
echo "to compile on systems with systemd : make systemd"
echo "to compile on other systems : make"
;;
Darwin)
echo "you need to download release from github or build binaries from source"
echo "to compile : make mac"
;;
FreeBSD)
echo "you need to download release from github or build binaries from source"
echo "to compile : make"
;;
OpenBSD)
echo "to compile : make bsd"
;;
CYGWIN*)
echo "you need to download release from github or build binaries from source"
echo "to compile : read docs"
echo "to make things easier use zapret-win-bundle"
;;
esac
exit 1
fi
unset PKTWS
case $UNAME in
Linux)
ARCHLIST="my x86_64 x86 aarch64 arm mips64r2-msb mips32r1-lsb mips32r1-msb lexra ppc"
ARCHLIST="my linux-x86_64 linux-x86 linux-arm64 linux-arm linux-mips64 linux-mipsel linux-mips linux-lexra linux-ppc"
PKTWS=nfqws
;;
Darwin)
ARCHLIST="my mac64"
;;
FreeBSD)
ARCHLIST="my freebsd-x64"
ARCHLIST="my freebsd-x86_64"
PKTWS=dvtws
;;
CYGWIN*)
UNAME=CYGWIN
ARCHLIST="win64 win32"
ARCHLIST="windows-x86_64 windows-x86"
PKTWS=winws
;;
*)
ARCHLIST="my"
esac
select_test_method
if [ "$1" = "getarch" ]; then
for arch in $ARCHLIST
do
@@ -85,6 +196,8 @@ if [ "$1" = "getarch" ]; then
fi
done
else
echo "using arch detect method : $TEST${ELF_ARCH:+ $ELF_ARCH}"
for arch in $ARCHLIST
do
[ -d "$BINDIR/$arch" ] || continue

View File

@@ -50,6 +50,29 @@ check_readonly_system()
}
}
check_source()
{
local bad=0
echo \* checking source files
case $SYSTEM in
systemd)
[ -f "$EXEDIR/init.d/systemd/zapret.service" ] || bad=1
;;
openrc)
[ -f "$EXEDIR/init.d/openrc/zapret" ] || bad=1
;;
macos)
[ -f "$EXEDIR/init.d/macos/zapret" ] || bad=1
;;
esac
[ "$bad" = 1 ] && {
echo 'some critical files are missing'
echo 'are you sure you are not using embedded release ? you need full version for traditional systems'
exitp 5
}
}
check_bins()
{
echo \* checking executables
@@ -57,6 +80,7 @@ check_bins()
fix_perms_bin_test "$EXEDIR"
local arch="$(get_bin_arch)"
local make_target
local cf="-march=native"
[ "$FORCE_BUILD" = "1" ] && {
echo forced build mode
if [ "$arch" = "my" ]; then
@@ -69,8 +93,16 @@ check_bins()
echo found architecture "\"$arch\""
elif [ -f "$EXEDIR/Makefile" ] && exists make; then
echo trying to compile
[ "$SYSTEM" = "macos" ] && make_target=mac
make -C "$EXEDIR" $make_target || {
case $SYSTEM in
macos)
make_target=mac
cf=
;;
systemd)
make_target=systemd
;;
esac
CFLAGS="${cf:+$cf }${CFLAGS}" OPTIMIZE=-O2 make -C "$EXEDIR" $make_target || {
echo could not compile
make -C "$EXEDIR" clean
exitp 8
@@ -223,9 +255,9 @@ select_mode_filter()
select_mode()
{
select_mode_filter
select_mode_mode
select_mode_iface
select_mode_filter
}
select_getlist()
@@ -292,7 +324,7 @@ ask_config_tmpdir()
echo default tmpfs has size of 50% RAM
echo "RAM : $(get_ram_mb) Mb"
echo "DISK : $(get_free_space_mb) Mb"
echo select temp file location
echo select temp file location
[ -z "$TMPDIR" ] && TMPDIR=/tmp
ask_list TMPDIR "/tmp $EXEDIR/tmp" && {
[ "$TMPDIR" = "/tmp" ] && TMPDIR=
@@ -388,7 +420,7 @@ copy_openwrt()
local ARCH="$(get_bin_arch)"
local BINDIR="$1/binaries/$ARCH"
local file
[ -d "$2" ] || mkdir -p "$2"
mkdir "$2/tpws" "$2/nfq" "$2/ip2net" "$2/mdig" "$2/binaries" "$2/binaries/$ARCH" "$2/init.d" "$2/tmp" "$2/files"
@@ -482,7 +514,7 @@ _restore_settings()
[ -z "$f" -o "$f" = "/" ] && continue
[ -f "/tmp/zapret-bkp-$i" ] && {
mv -f "/tmp/zapret-bkp-$i" "$ZAPRET_TARGET/$f" || rm -f "/tmp/zapret-bkp-$i"
mv -f "/tmp/zapret-bkp-$i" "$ZAPRET_TARGET/$f" || rm -f "/tmp/zapret-bkp-$i"
}
[ -d "/tmp/zapret-bkp-$i" ] && {
[ -d "$ZAPRET_TARGET/$f" ] && rm -r "$ZAPRET_TARGET/$f"
@@ -724,7 +756,7 @@ install_linux()
crontab_del_quiet
# desktop system. more likely up at daytime
crontab_add 10 22
echo
echo '!!! WARNING. YOUR SETUP IS INCOMPLETE !!!'
echo you must manually add to auto start : $INIT_SCRIPT_SRC start
@@ -772,7 +804,6 @@ deoffload_openwrt_firewall()
else
echo system wide software flow offloading disabled. ok
fi
}
@@ -877,8 +908,7 @@ umask 0022
fix_sbin_path
fsleep_setup
check_system
[ "$SYSTEM" = "macos" ] && . "$EXEDIR/init.d/macos/functions"
check_source
case $SYSTEM in
systemd)

View File

@@ -1,5 +1,6 @@
CC ?= gcc
CFLAGS += -std=gnu99 -Os -flto=auto
CC ?= cc
OPTIMIZE ?= -Os
CFLAGS += -std=gnu99 $(OPTIMIZE) -flto=auto
CFLAGS_BSD = -Wno-address-of-packed-member
CFLAGS_WIN = -static
LIBS =
@@ -11,6 +12,8 @@ all: ip2net
ip2net: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o ip2net $(SRC_FILES) $(LIBS) $(LDFLAGS)
systemd: ip2net
android: ip2net
bsd: $(SRC_FILES)

View File

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

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,17 @@ 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$
pkill -HUP ^nfqws$
pkill -HUP ^dvtws$
else
echo no mass killer available ! cant HUP zapret daemons
fi
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,6 @@
CC ?= gcc
CFLAGS += -std=gnu99 -Os
CC ?= cc
OPTIMIZE ?= -Os
CFLAGS += -std=gnu99 $(OPTIMIZE)
CFLAGS_BSD = -Wno-address-of-packed-member
CFLAGS_WIN = -static
LIBS = -lpthread
@@ -12,6 +13,8 @@ all: mdig
mdig: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o mdig $(SRC_FILES) $(LIBS) $(LDFLAGS)
systemd: mdig
android: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o mdig $(SRC_FILES) $(LIBS_ANDROID) $(LDFLAGS)

View File

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

View File

@@ -1,5 +1,6 @@
CC ?= cc
CFLAGS += -std=gnu99 -s -Os -Wno-address-of-packed-member -flto=auto
OPTIMIZE ?= -Os
CFLAGS += -std=gnu99 -s $(OPTIMIZE) -flto=auto -Wno-address-of-packed-member
LIBS = -lz
SRC_FILES = *.c crypto/*.c

View File

@@ -1,8 +1,12 @@
CC ?= gcc
CFLAGS += -std=gnu99 -Os -flto=auto
CC ?= cc
OPTIMIZE ?= -Os
CFLAGS += -std=gnu99 $(OPTIMIZE) -flto=auto
CFLAGS_SYSTEMD = -DUSE_SYSTEMD
CFLAGS_BSD = -Wno-address-of-packed-member
CFLAGS_CYGWIN = -Wno-address-of-packed-member -static
LIBS_LINUX = -lnetfilter_queue -lnfnetlink -lz
LDFLAGS_ANDROID = -llog
LIBS_LINUX = -lz -lnetfilter_queue -lnfnetlink -lmnl
LIBS_SYSTEMD = -lsystemd
LIBS_BSD = -lz
LIBS_CYGWIN = -lz -Lwindows/windivert -Iwindows -lwlanapi -lole32 -loleaut32
LIBS_CYGWIN32 = -lwindivert32
@@ -16,7 +20,11 @@ all: nfqws
nfqws: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o nfqws $(SRC_FILES) $(LIBS_LINUX) $(LDFLAGS)
android: nfqws
systemd: $(SRC_FILES)
$(CC) -s $(CFLAGS) $(CFLAGS_SYSTEMD) -o nfqws $(SRC_FILES) $(LIBS_LINUX) $(LIBS_SYSTEMD) $(LDFLAGS)
android: $(SRC_FILES)
$(CC) -s $(CFLAGS) -o nfqws $(SRC_FILES) $(LIBS_LINUX) $(LDFLAGS) $(LDFLAGS_ANDROID)
bsd: $(SRC_FILES)
$(CC) -s $(CFLAGS) $(CFLAGS_BSD) -o dvtws $(SRC_FILES) $(LIBS_BSD) $(LDFLAGS)

View File

@@ -27,11 +27,9 @@ 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;
track->hostname_is_ip = false;
}
static void ConntrackClearTrack(t_ctrack *track)
{
@@ -146,8 +144,11 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
}
else if (tcp_synack_segment(tcphdr))
{
if (t->state!=SYN) ConntrackReInitTrack(t); // erase current entry
if (!t->seq0) t->seq0 = ntohl(tcphdr->th_ack)-1;
// ignore SA dups
uint32_t seq0 = ntohl(tcphdr->th_ack)-1;
if (t->state!=SYN && t->seq0!=seq0)
ConntrackReInitTrack(t); // erase current entry
if (!t->seq0) t->seq0 = seq0;
t->ack0 = ntohl(tcphdr->th_seq);
}
else if (tcphdr->th_flags & (TH_FIN|TH_RST))
@@ -341,19 +342,16 @@ void ConntrackPoolDump(const t_conntrack *p)
printf("rseq=%u pos_orig=%u rack=%u pos_reply=%u",
t->track.seq_last, t->track.pos_orig,
t->track.ack_last, t->track.pos_reply);
printf(" req_retrans=%u cutoff=%u wss_cutoff=%u d_cutoff=%u hostname=%s l7proto=%s\n",
t->track.req_retrans_counter, t->track.b_cutoff, t->track.b_wssize_cutoff, t->track.b_desync_cutoff, t->track.hostname, l7proto_str(t->track.l7proto));
printf(" req_retrans=%u cutoff=%u wss_cutoff=%u desync_cutoff=%u dup_cutoff=%u orig_cutoff=%u hostname=%s l7proto=%s\n",
t->track.req_retrans_counter, t->track.b_cutoff, t->track.b_wssize_cutoff, t->track.b_desync_cutoff, t->track.b_dup_cutoff, t->track.b_orig_mod_cutoff, t->track.hostname, l7proto_str(t->track.l7proto));
};
}
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

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

View File

@@ -5,9 +5,11 @@ int aes_gcm_crypt(int mode, uint8_t *output, const uint8_t *input, size_t input_
int ret = 0;
gcm_context ctx;
gcm_setkey(&ctx, key, (const uint)key_len);
ret = gcm_crypt_and_tag(&ctx, mode, iv, iv_len, adata, adata_len, input, output, input_length, atag, atag_len);
gcm_zero_ctx(&ctx);
if (!(ret = gcm_setkey(&ctx, key, (const uint)key_len)))
{
ret = gcm_crypt_and_tag(&ctx, mode, iv, iv_len, adata, adata_len, input, output, input_length, atag, atag_len);
gcm_zero_ctx(&ctx);
}
return ret;
}

View File

@@ -367,7 +367,7 @@ int aes_setkey(aes_context *ctx, // AES context provided by our caller
}
#if AES_DECRYPTION
if (mode == DECRYPT) // expand our key for encryption or decryption
if (mode == AES_DECRYPT) // expand our key for encryption or decryption
return(aes_set_decryption_key(ctx, key, keysize));
else /* ENCRYPT */
#endif /* AES_DECRYPTION */
@@ -399,7 +399,7 @@ int aes_cipher(aes_context *ctx,
#if AES_DECRYPTION // whether AES decryption is supported
if (ctx->mode == DECRYPT)
if (ctx->mode == AES_DECRYPT)
{
for (i = (ctx->rounds >> 1) - 1; i > 0; i--)
{

View File

@@ -246,7 +246,7 @@ int gcm_setkey(gcm_context *ctx, // pointer to caller-provided gcm context
*
******************************************************************************/
int gcm_start(gcm_context *ctx, // pointer to user-provided GCM context
int mode, // GCM_ENCRYPT or GCM_DECRYPT
int mode, // AES_ENCRYPT or AES_DECRYPT
const uchar *iv, // pointer to initialization vector
size_t iv_len, // IV length in bytes (should == 12)
const uchar *add, // ptr to additional AEAD data (NULL if none)
@@ -288,6 +288,7 @@ int gcm_start(gcm_context *ctx, // pointer to user-provided GCM context
for (i = 0; i < 16; i++) ctx->y[i] ^= work_buf[i];
gcm_mult(ctx, ctx->y, ctx->y);
}
if ((ret = aes_cipher(&ctx->aes_ctx, ctx->y, ctx->base_ectr)) != 0)
return(ret);
@@ -427,7 +428,7 @@ int gcm_finish(gcm_context *ctx, // pointer to user-provided GCM context
******************************************************************************/
int gcm_crypt_and_tag(
gcm_context *ctx, // gcm context with key already setup
int mode, // cipher direction: GCM_ENCRYPT or GCM_DECRYPT
int mode, // cipher direction: AES_ENCRYPT or AES_DECRYPT
const uchar *iv, // pointer to the 12-byte initialization vector
size_t iv_len, // byte length if the IV. should always be 12
const uchar *add, // pointer to the non-ciphered additional data

View File

@@ -29,6 +29,16 @@
#endif
#ifdef __linux__
#include <linux/nl80211.h>
#include <linux/genetlink.h>
#include <libmnl/libmnl.h>
#include <net/if.h>
#define _LINUX_IF_H // prevent conflict between linux/if.h and net/if.h in old gcc 4.x
#include <linux/wireless.h>
#include <sys/ioctl.h>
#endif
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment)
{
return htonl(ntohl(netorder_value)+cpuorder_increment);
@@ -38,6 +48,11 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment)
return htons(ntohs(netorder_value)+cpuorder_increment);
}
bool ip_has_df(const struct ip *ip)
{
return ip && !!(ntohs(ip->ip_off) & IP_DF);
}
uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind)
{
uint8_t *t = (uint8_t*)(tcp+1);
@@ -83,14 +98,27 @@ bool tcp_has_fastopen(const struct tcphdr *tcp)
opt = tcp_find_option((struct tcphdr*)tcp, 254);
return opt && opt[1]>=4 && opt[2]==0xF9 && opt[3]==0x89;
}
uint16_t tcp_find_mss(struct tcphdr *tcp)
{
uint8_t *t = tcp_find_option(tcp,2);
return (t && t[1]==4) ? *(uint16_t*)(t+2) : 0;
}
bool tcp_has_sack(struct tcphdr *tcp)
{
uint8_t *t = tcp_find_option(tcp,4);
return !!t;
}
// n prefix (nsport, nwsize) means network byte order
static void fill_tcphdr(
struct tcphdr *tcp, uint32_t fooling, uint8_t tcp_flags,
struct tcphdr *tcp, uint32_t fooling, uint16_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq,
uint16_t nsport, uint16_t ndport,
uint16_t nwsize, uint8_t scale_factor,
uint32_t *timestamps,
uint32_t ts_increment,
uint32_t badseq_increment,
uint32_t badseq_ack_increment,
uint16_t data_len)
@@ -111,28 +139,41 @@ static void fill_tcphdr(
tcp->th_seq = nseq;
tcp->th_ack = nack_seq;
}
tcp->th_off = 5;
tcp->th_off = 5;
if ((fooling & FOOL_DATANOACK) && !(tcp_flags & (TH_SYN|TH_RST)) && data_len)
tcp_flags &= ~TH_ACK;
*((uint8_t*)tcp+13)= tcp_flags;
tcp->th_flags = (uint8_t)tcp_flags;
tcp->th_x2 = (tcp_flags>>8) & 0xF;
tcp->th_win = nwsize;
if (nmss)
{
tcpopt[t++] = 2; // kind
tcpopt[t++] = 4; // len
*(uint16_t*)(tcpopt+t) = nmss;
t+=2;
}
if (sack)
{
tcpopt[t++] = 4; // kind
tcpopt[t++] = 2; // len
}
if (fooling & FOOL_MD5SIG)
{
tcpopt[0] = 19; // kind
tcpopt[1] = 18; // len
*(uint32_t*)(tcpopt+2)=random();
*(uint32_t*)(tcpopt+6)=random();
*(uint32_t*)(tcpopt+10)=random();
*(uint32_t*)(tcpopt+14)=random();
t=18;
tcpopt[t] = 19; // kind
tcpopt[t+1] = 18; // len
*(uint32_t*)(tcpopt+t+2)=random();
*(uint32_t*)(tcpopt+t+6)=random();
*(uint32_t*)(tcpopt+t+10)=random();
*(uint32_t*)(tcpopt+t+14)=random();
t+=18;
}
if (timestamps || (fooling & FOOL_TS))
if (timestamps)
{
tcpopt[t] = 8; // kind
tcpopt[t+1] = 10; // len
// forge only TSecr if orig timestamp is present
*(uint32_t*)(tcpopt+t+2) = timestamps ? timestamps[0] : -1;
*(uint32_t*)(tcpopt+t+6) = (timestamps && !(fooling & FOOL_TS)) ? timestamps[1] : -1;
memcpy(tcpopt+t+2,timestamps,8);
// forge TSval, keep TSecr
if (fooling & FOOL_TS) *(uint32_t*)(tcpopt+t+2) = net32_add(*(uint32_t*)(tcpopt+t+2),ts_increment);
t+=10;
}
if (scale_factor!=SCALE_NONE)
@@ -145,10 +186,12 @@ static void fill_tcphdr(
tcp->th_off += t>>2;
tcp->th_sum = 0;
}
static uint16_t tcpopt_len(uint32_t fooling, const uint32_t *timestamps, uint8_t scale_factor)
static uint16_t tcpopt_len(bool sack, bool mss, uint32_t fooling, const uint32_t *timestamps, uint8_t scale_factor)
{
uint16_t t=0;
if (fooling & FOOL_MD5SIG) t=18;
if (sack) t+=2;
if (mss) t+=4;
if (fooling & FOOL_MD5SIG) t+=18;
if ((fooling & FOOL_TS) || timestamps) t+=10;
if (scale_factor!=SCALE_NONE) t+=3;
return (t+3)&~3;
@@ -163,11 +206,11 @@ static void fill_udphdr(struct udphdr *udp, uint16_t nsport, uint16_t ndport, ui
udp->uh_sum = 0;
}
static void fill_iphdr(struct ip *ip, const struct in_addr *src, const struct in_addr *dst, uint16_t pktlen, uint8_t proto, uint8_t ttl, uint8_t tos, uint16_t ip_id)
static void fill_iphdr(struct ip *ip, const struct in_addr *src, const struct in_addr *dst, uint16_t pktlen, uint8_t proto, bool DF, uint8_t ttl, uint8_t tos, uint16_t ip_id)
{
ip->ip_tos = tos;
ip->ip_sum = 0;
ip->ip_off = 0;
ip->ip_off = DF ? htons(IP_DF) : 0;
ip->ip_v = 4;
ip->ip_hl = 5;
ip->ip_len = htons(pktlen);
@@ -189,21 +232,25 @@ static void fill_ip6hdr(struct ip6_hdr *ip6, const struct in6_addr *src, const s
bool prepare_tcp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst,
uint8_t tcp_flags,
uint16_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq,
uint16_t nwsize,
uint8_t scale_factor,
uint32_t *timestamps,
bool DF,
uint8_t ttl,
uint8_t tos,
uint16_t ip_id,
uint32_t fooling,
uint32_t ts_increment,
uint32_t badseq_increment,
uint32_t badseq_ack_increment,
const void *data, uint16_t len,
uint8_t *buf, size_t *buflen)
{
uint16_t tcpoptlen = tcpopt_len(fooling,timestamps,scale_factor);
uint16_t tcpoptlen = tcpopt_len(sack,!!nmss,fooling,timestamps,scale_factor);
uint16_t ip_payload_len = sizeof(struct tcphdr) + tcpoptlen + len;
uint16_t pktlen = sizeof(struct ip) + ip_payload_len;
if (pktlen>*buflen) return false;
@@ -212,12 +259,12 @@ bool prepare_tcp_segment4(
struct tcphdr *tcp = (struct tcphdr*)(ip+1);
uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen;
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_TCP, ttl, tos, ip_id);
fill_tcphdr(tcp,fooling,tcp_flags,nseq,nack_seq,src->sin_port,dst->sin_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment,len);
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_TCP, DF, ttl, tos, ip_id);
fill_tcphdr(tcp,fooling,tcp_flags,sack,nmss,nseq,nack_seq,src->sin_port,dst->sin_port,nwsize,scale_factor,timestamps,ts_increment,badseq_increment,badseq_ack_increment,len);
memcpy(payload,data,len);
tcp4_fix_checksum(tcp,ip_payload_len,&ip->ip_src,&ip->ip_dst);
if (fooling & FOOL_BADSUM) tcp->th_sum^=htons(0xBEAF);
if (fooling & FOOL_BADSUM) tcp->th_sum^=(uint16_t)(1+random()%0xFFFF);
*buflen = pktlen;
return true;
@@ -225,7 +272,9 @@ bool prepare_tcp_segment4(
bool prepare_tcp_segment6(
const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst,
uint8_t tcp_flags,
uint16_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq,
uint16_t nwsize,
uint8_t scale_factor,
@@ -233,12 +282,13 @@ bool prepare_tcp_segment6(
uint8_t ttl,
uint32_t flow_label,
uint32_t fooling,
uint32_t ts_increment,
uint32_t badseq_increment,
uint32_t badseq_ack_increment,
const void *data, uint16_t len,
uint8_t *buf, size_t *buflen)
{
uint16_t tcpoptlen = tcpopt_len(fooling,timestamps,scale_factor);
uint16_t tcpoptlen = tcpopt_len(sack,!!nmss,fooling,timestamps,scale_factor);
uint16_t transport_payload_len = sizeof(struct tcphdr) + tcpoptlen + len;
uint16_t ip_payload_len = transport_payload_len +
8*!!((fooling & (FOOL_HOPBYHOP|FOOL_HOPBYHOP2))==FOOL_HOPBYHOP) +
@@ -297,11 +347,11 @@ bool prepare_tcp_segment6(
uint8_t *payload = (uint8_t*)(tcp+1)+tcpoptlen;
fill_ip6hdr(ip6, &src->sin6_addr, &dst->sin6_addr, ip_payload_len, proto, ttl, flow_label);
fill_tcphdr(tcp,fooling,tcp_flags,nseq,nack_seq,src->sin6_port,dst->sin6_port,nwsize,scale_factor,timestamps,badseq_increment,badseq_ack_increment,len);
fill_tcphdr(tcp,fooling,tcp_flags,sack,nmss,nseq,nack_seq,src->sin6_port,dst->sin6_port,nwsize,scale_factor,timestamps,ts_increment,badseq_increment,badseq_ack_increment,len);
memcpy(payload,data,len);
tcp6_fix_checksum(tcp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst);
if (fooling & FOOL_BADSUM) tcp->th_sum^=htons(0xBEAF);
if (fooling & FOOL_BADSUM) tcp->th_sum^=(1+random()%0xFFFF);
*buflen = pktlen;
return true;
@@ -309,25 +359,29 @@ bool prepare_tcp_segment6(
bool prepare_tcp_segment(
const struct sockaddr *src, const struct sockaddr *dst,
uint8_t tcp_flags,
uint16_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq,
uint16_t nwsize,
uint8_t scale_factor,
uint32_t *timestamps,
bool DF,
uint8_t ttl,
uint8_t tos,
uint16_t ip_id,
uint32_t flow_label,
uint32_t fooling,
uint32_t ts_increment,
uint32_t badseq_increment,
uint32_t badseq_ack_increment,
const void *data, uint16_t len,
uint8_t *buf, size_t *buflen)
{
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,tos,ip_id,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
prepare_tcp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,tcp_flags,sack,nmss,nseq,nack_seq,nwsize,scale_factor,timestamps,DF,ttl,tos,ip_id,fooling,ts_increment,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
(src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ?
prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,flow_label,fooling,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
prepare_tcp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,tcp_flags,sack,nmss,nseq,nack_seq,nwsize,scale_factor,timestamps,ttl,flow_label,fooling,ts_increment,badseq_increment,badseq_ack_increment,data,len,buf,buflen) :
false;
}
@@ -335,6 +389,7 @@ bool prepare_tcp_segment(
// padlen<0 means payload shrinking
bool prepare_udp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst,
bool DF,
uint8_t ttl,
uint8_t tos,
uint16_t ip_id,
@@ -361,16 +416,16 @@ bool prepare_udp_segment4(
uint8_t *payload = (uint8_t*)(udp+1);
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_UDP, ttl, tos, ip_id);
fill_iphdr(ip, &src->sin_addr, &dst->sin_addr, pktlen, IPPROTO_UDP, DF, ttl, tos, ip_id);
fill_udphdr(udp, src->sin_port, dst->sin_port, datalen);
memcpy(payload,data,len);
if (padding)
fill_pattern(payload+len,padlen,padding,padding_size);
fill_pattern(payload+len,padlen,padding,padding_size,0);
else
memset(payload+len,0,padlen);
udp4_fix_checksum(udp,ip_payload_len,&ip->ip_src,&ip->ip_dst);
if (fooling & FOOL_BADSUM) udp->uh_sum^=htons(0xBEAF);
if (fooling & FOOL_BADSUM) udp->uh_sum^=(1+random()%0xFFFF);
*buflen = pktlen;
return true;
@@ -455,17 +510,18 @@ bool prepare_udp_segment6(
memcpy(payload,data,len);
if (padding)
fill_pattern(payload+len,padlen,padding,padding_size);
fill_pattern(payload+len,padlen,padding,padding_size,0);
else
memset(payload+len,0,padlen);
udp6_fix_checksum(udp,transport_payload_len,&ip6->ip6_src,&ip6->ip6_dst);
if (fooling & FOOL_BADSUM) udp->uh_sum^=htons(0xBEAF);
if (fooling & FOOL_BADSUM) udp->uh_sum^=(1+random()%0xFFFF);
*buflen = pktlen;
return true;
}
bool prepare_udp_segment(
const struct sockaddr *src, const struct sockaddr *dst,
bool DF,
uint8_t ttl,
uint8_t tos,
uint16_t ip_id,
@@ -477,7 +533,7 @@ bool prepare_udp_segment(
uint8_t *buf, size_t *buflen)
{
return (src->sa_family==AF_INET && dst->sa_family==AF_INET) ?
prepare_udp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,ttl,tos,ip_id,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
prepare_udp_segment4((struct sockaddr_in *)src,(struct sockaddr_in *)dst,DF,ttl,tos,ip_id,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
(src->sa_family==AF_INET6 && dst->sa_family==AF_INET6) ?
prepare_udp_segment6((struct sockaddr_in6 *)src,(struct sockaddr_in6 *)dst,ttl,flow_label,fooling,padding,padding_size,padlen,data,len,buf,buflen) :
false;
@@ -601,12 +657,45 @@ bool ip_frag(
return false;
}
void rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl)
bool rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl)
{
if (ip) ip->ip_ttl = ttl;
if (ip6) ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim = ttl;
if (ttl)
{
if (ip)
{
if (ip->ip_ttl!=ttl)
{
ip->ip_ttl = ttl;
ip4_fix_checksum(ip);
return true;
}
}
else if (ip6)
{
if (ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim!=ttl)
{
ip6->ip6_ctlun.ip6_un1.ip6_un1_hlim = ttl;
return true;
}
}
}
return false;
}
void apply_tcp_flags(struct tcphdr *tcp, uint16_t fl)
{
if (tcp)
{
tcp->th_flags = (uint8_t)fl;
tcp->th_x2 = (fl>>8) & 0xF;
}
}
uint16_t get_tcp_flags(const struct tcphdr *tcp)
{
return tcp->th_flags | (tcp->th_x2<<8);
}
void extract_ports(const struct tcphdr *tcphdr, const struct udphdr *udphdr, uint8_t *proto, uint16_t *sport, uint16_t *dport)
{
@@ -847,7 +936,6 @@ void proto_skip_ipv6(uint8_t **data, size_t *len, uint8_t *proto_type, uint8_t *
{
case 0: // Hop-by-Hop Options
case 43: // routing
case 51: // authentication
case 60: // Destination Options
case 135: // mobility
case 139: // Host Identity Protocol Version v2
@@ -858,6 +946,11 @@ void proto_skip_ipv6(uint8_t **data, size_t *len, uint8_t *proto_type, uint8_t *
case 44: // fragment. length fixed to 8, hdrlen field defined as reserved
hdrlen = 8;
break;
case 51: // authentication
// special case. length in ah header is in 32-bit words minus 2
if (*len < 2) return; // error
hdrlen = 8 + ((*data)[1] << 2);
break;
case 59: // no next header
return; // error
default:
@@ -1747,7 +1840,9 @@ nofix:
bytes = sendto(sock, data, len, 0, (struct sockaddr*)&dst2, salen);
if (bytes==-1)
{
DLOG_PERROR("rawsend: sendto");
char s[40];
snprintf(s,sizeof(s),"rawsend: sendto (%zu)",len);
DLOG_PERROR(s);
return false;
}
return true;
@@ -1770,16 +1865,268 @@ bool rawsend_queue(struct rawpacket_tailhead *q)
}
// return guessed fake ttl value. 0 means unsuccessfull, should not perform autottl fooling
// ttl = TTL of incoming packet
uint8_t autottl_guess(uint8_t ttl, const autottl *attl)
{
uint8_t orig, path, fake;
#if defined(HAS_FILTER_SSID) && defined(__linux__)
// linux-specific wlan retrieval implementation
typedef void netlink_prepare_nlh_cb_t(struct nlmsghdr *nlh);
static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, uint16_t flags, uint8_t cmd, uint8_t version, netlink_prepare_nlh_cb_t cb_prepare_nlh, mnl_cb_t cb_data, void *data)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
struct genlmsghdr *genl;
ssize_t rd;
nlh = mnl_nlmsg_put_header(buf);
nlh->nlmsg_type = type;
nlh->nlmsg_flags = flags;
genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr));
genl->cmd = cmd;
genl->version = version;
if (cb_prepare_nlh) cb_prepare_nlh(nlh);
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
{
DLOG_PERROR("mnl_socket_sendto");
return false;
}
while ((rd=mnl_socket_recvfrom(nl, buf, sizeof(buf))) > 0)
{
switch(mnl_cb_run(buf, rd, 0, 0, cb_data, data))
{
case MNL_CB_STOP:
return true;
case MNL_CB_OK:
break;
default:
return false;
}
}
return false;
}
static void wlan_id_prepare(struct nlmsghdr *nlh)
{
mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, "nl80211");
}
static int wlan_id_attr_cb(const struct nlattr *attr, void *data)
{
if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0)
{
DLOG_PERROR("mnl_attr_type_valid");
return MNL_CB_ERROR;
}
switch(mnl_attr_get_type(attr))
{
case CTRL_ATTR_FAMILY_ID:
if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
{
DLOG_PERROR("mnl_attr_validate(family_id)");
return MNL_CB_ERROR;
}
*((uint16_t*)data) = mnl_attr_get_u16(attr);
break;
}
return MNL_CB_OK;
}
static int wlan_id_cb(const struct nlmsghdr *nlh, void *data)
{
return mnl_attr_parse(nlh, sizeof(struct genlmsghdr), wlan_id_attr_cb, data);
}
static uint16_t wlan_get_family_id(struct mnl_socket* nl)
{
uint16_t id;
return netlink_genl_simple_transact(nl, GENL_ID_CTRL, NLM_F_REQUEST | NLM_F_ACK, CTRL_CMD_GETFAMILY, 1, wlan_id_prepare, wlan_id_cb, &id) ? id : 0;
}
static int wlan_info_attr_cb(const struct nlattr *attr, void *data)
{
struct wlan_interface *wlan = (struct wlan_interface *)data;
switch(mnl_attr_get_type(attr))
{
case NL80211_ATTR_IFINDEX:
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
{
DLOG_PERROR("mnl_attr_validate(ifindex)");
return MNL_CB_ERROR;
}
wlan->ifindex = mnl_attr_get_u32(attr);
break;
case NL80211_ATTR_SSID:
if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
{
DLOG_PERROR("mnl_attr_validate(ssid)");
return MNL_CB_ERROR;
}
snprintf(wlan->ssid,sizeof(wlan->ssid),"%s",mnl_attr_get_str(attr));
break;
case NL80211_ATTR_IFNAME:
if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
{
DLOG_PERROR("mnl_attr_validate(ifname)");
return MNL_CB_ERROR;
}
snprintf(wlan->ifname,sizeof(wlan->ifname),"%s",mnl_attr_get_str(attr));
break;
}
return MNL_CB_OK;
}
static int wlan_info_cb(const struct nlmsghdr *nlh, void *data)
{
int ret;
struct wlan_interface_collection *wc = (struct wlan_interface_collection*)data;
if (wc->count>=WLAN_INTERFACE_MAX) return MNL_CB_OK;
memset(wc->wlan+wc->count,0,sizeof(wc->wlan[0]));
ret = mnl_attr_parse(nlh, sizeof(struct genlmsghdr), wlan_info_attr_cb, wc->wlan+wc->count);
if (ret>=0 && *wc->wlan[wc->count].ifname && wc->wlan[wc->count].ifindex)
{
if (*wc->wlan[wc->count].ssid)
wc->count++;
else
{
// sometimes nl80211 does not return SSID but wireless ext does
int wext_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (wext_fd!=-1)
{
struct iwreq req;
snprintf(req.ifr_ifrn.ifrn_name,sizeof(req.ifr_ifrn.ifrn_name),"%s",wc->wlan[wc->count].ifname);
req.u.essid.pointer = wc->wlan[wc->count].ssid;
req.u.essid.length = sizeof(wc->wlan[wc->count].ssid);
req.u.essid.flags = 0;
if (ioctl(wext_fd, SIOCGIWESSID, &req)!=-1)
if (*wc->wlan[wc->count].ssid)
wc->count++;
close(wext_fd);
}
}
}
return ret;
}
static bool wlan_info(struct mnl_socket* nl, uint16_t wlan_family_id, struct wlan_interface_collection* w)
{
return netlink_genl_simple_transact(nl, wlan_family_id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP, NL80211_CMD_GET_INTERFACE, 0, NULL, wlan_info_cb, w);
}
static bool wlan_init80211(struct mnl_socket** nl)
{
if (!(*nl = mnl_socket_open(NETLINK_GENERIC)))
{
DLOG_PERROR("mnl_socket_open");
return false;
}
if (mnl_socket_bind(*nl, 0, MNL_SOCKET_AUTOPID))
{
DLOG_PERROR("mnl_socket_bind");
return false;
}
return true;
}
static void wlan_deinit80211(struct mnl_socket** nl)
{
if (*nl)
{
mnl_socket_close(*nl);
*nl = NULL;
}
}
static time_t wlan_info_last = 0;
static bool wlan_info_rate_limited(struct mnl_socket* nl, uint16_t wlan_family_id, struct wlan_interface_collection* w)
{
bool bres = true;
time_t now = time(NULL);
// do not purge too often to save resources
if (wlan_info_last != now)
{
bres = wlan_info(nl,wlan_family_id,w);
wlan_info_last = now;
}
return bres;
}
static struct mnl_socket* nl_wifi = NULL;
static uint16_t id_nl80211;
struct wlan_interface_collection wlans = { .count = 0 };
void wlan_info_deinit(void)
{
wlan_deinit80211(&nl_wifi);
}
bool wlan_info_init(void)
{
wlan_info_deinit();
if (!wlan_init80211(&nl_wifi)) return false;
if (!(id_nl80211 = wlan_get_family_id(nl_wifi)))
{
wlan_info_deinit();
return false;
}
return true;
}
bool wlan_info_get(void)
{
return wlan_info(nl_wifi, id_nl80211, &wlans);
}
bool wlan_info_get_rate_limited(void)
{
return wlan_info_rate_limited(nl_wifi, id_nl80211, &wlans);
}
#endif
#ifdef HAS_FILTER_SSID
const char *wlan_ifname2ssid(const struct wlan_interface_collection *w, const char *ifname)
{
int i;
if (ifname)
{
for (i=0;i<w->count;i++)
if (!strcmp(w->wlan[i].ifname,ifname))
return w->wlan[i].ssid;
}
return NULL;
}
const char *wlan_ifidx2ssid(const struct wlan_interface_collection *w,int ifidx)
{
int i;
for (i=0;i<w->count;i++)
if (w->wlan[i].ifindex == ifidx)
return w->wlan[i].ssid;
return NULL;
}
const char *wlan_ssid_search_ifname(const char *ifname)
{
return wlan_ifname2ssid(&wlans,ifname);
}
const char *wlan_ssid_search_ifidx(int ifidx)
{
return wlan_ifidx2ssid(&wlans,ifidx);
}
#endif
uint8_t hop_count_guess(uint8_t ttl)
{
// 18.65.168.125 ( cloudfront ) 255
// 157.254.246.178 128
// 1.1.1.1 64
// guess original ttl. consider path lengths less than 32 hops
uint8_t orig;
if (ttl>223)
orig=255;
else if (ttl<128 && ttl>96)
@@ -1789,13 +2136,21 @@ uint8_t autottl_guess(uint8_t ttl, const autottl *attl)
else
return 0;
path = orig - ttl;
return orig - ttl;
}
// return guessed fake ttl value. 0 means unsuccessfull, should not perform autottl fooling
uint8_t autottl_eval(uint8_t hop_count, const autottl *attl)
{
uint8_t fake;
int d;
fake = path > attl->delta ? path - attl->delta : attl->min;
if (fake<attl->min) fake=attl->min;
else if (fake>attl->max) fake=attl->max;
d = (int)hop_count + attl->delta;
if (d<attl->min) fake=attl->min;
else if (d>attl->max) fake=attl->max;
else fake=(uint8_t)d;
if (fake>=path) return 0;
if (attl->delta<0 && fake>=hop_count || attl->delta>=0 && fake<hop_count)
return 0;
return fake;
}
@@ -1847,15 +2202,15 @@ void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transpo
{
if (!(verdict & VERDICT_NOCSUM))
{
#ifdef __CYGWIN__
// always fix csum for windivert. original can be partial or bad
#ifndef __CYGWIN__
#ifdef __FreeBSD__
if ((verdict & VERDICT_MASK)!=VERDICT_DROP)
#elif defined(__FreeBSD__)
// FreeBSD tend to pass ipv6 frames with wrong checksum
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
#else
// if original packet was tampered earlier it needs checksum fixed
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
#endif
#endif
tcp_fix_checksum(tcphdr,transport_len,ip,ip6hdr);
}
@@ -1864,15 +2219,15 @@ void verdict_udp_csum_fix(uint8_t verdict, struct udphdr *udphdr, size_t transpo
{
if (!(verdict & VERDICT_NOCSUM))
{
#ifdef __CYGWIN__
// always fix csum for windivert. original can be partial or bad
#ifndef __CYGWIN__
#ifdef __FreeBSD__
if ((verdict & VERDICT_MASK)!=VERDICT_DROP)
#elif defined(__FreeBSD__)
// FreeBSD tend to pass ipv6 frames with wrong checksum
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY || ip6hdr)
#else
// if original packet was tampered earlier it needs checksum fixed
if ((verdict & VERDICT_MASK)==VERDICT_MODIFY)
#endif
#endif
udp_fix_checksum(udphdr,transport_len,ip,ip6hdr);
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include "nfqws.h"
#include "checksum.h"
#include "packet_queue.h"
#include "pools.h"
@@ -59,6 +60,7 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
#define VERDICT_DROP 2
#define VERDICT_MASK 3
#define VERDICT_NOCSUM 4
#define VERDICT_GARBAGE 8
#define IP4_TOS(ip_header) (ip_header ? ip_header->ip_tos : 0)
#define IP4_IP_ID(ip_header) (ip_header ? ip_header->ip_id : 0)
@@ -67,22 +69,28 @@ uint32_t net16_add(uint16_t netorder_value, uint16_t cpuorder_increment);
// seq and wsize have network byte order
bool prepare_tcp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst,
uint8_t tcp_flags,
uint16_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq,
uint16_t nwsize,
uint8_t scale_factor,
uint32_t *timestamps,
bool DF,
uint8_t ttl,
uint8_t tos,
uint16_t ip_id,
uint32_t fooling,
uint32_t ts_increment,
uint32_t badseq_increment,
uint32_t badseq_ack_increment,
const void *data, uint16_t len,
uint8_t *buf, size_t *buflen);
bool prepare_tcp_segment6(
const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst,
uint8_t tcp_flags,
uint16_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq,
uint16_t nwsize,
uint8_t scale_factor,
@@ -90,22 +98,27 @@ bool prepare_tcp_segment6(
uint8_t ttl,
uint32_t flow_label,
uint32_t fooling,
uint32_t ts_increment,
uint32_t badseq_increment,
uint32_t badseq_ack_increment,
const void *data, uint16_t len,
uint8_t *buf, size_t *buflen);
bool prepare_tcp_segment(
const struct sockaddr *src, const struct sockaddr *dst,
uint8_t tcp_flags,
uint16_t tcp_flags,
bool sack,
uint16_t nmss,
uint32_t nseq, uint32_t nack_seq,
uint16_t nwsize,
uint8_t scale_factor,
uint32_t *timestamps,
bool DF,
uint8_t ttl,
uint8_t tos,
uint16_t ip_id,
uint32_t flow_label,
uint32_t fooling,
uint32_t ts_increment,
uint32_t badseq_increment,
uint32_t badseq_ack_increment,
const void *data, uint16_t len,
@@ -114,6 +127,7 @@ bool prepare_tcp_segment(
bool prepare_udp_segment4(
const struct sockaddr_in *src, const struct sockaddr_in *dst,
bool DF,
uint8_t ttl,
uint8_t tos,
uint16_t ip_id,
@@ -133,6 +147,7 @@ bool prepare_udp_segment6(
uint8_t *buf, size_t *buflen);
bool prepare_udp_segment(
const struct sockaddr *src, const struct sockaddr *dst,
bool DF,
uint8_t ttl,
uint8_t tos,
uint16_t ip_id,
@@ -162,15 +177,22 @@ bool ip_frag(
uint8_t *pkt1, size_t *pkt1_size,
uint8_t *pkt2, size_t *pkt2_size);
void rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl);
bool rewrite_ttl(struct ip *ip, struct ip6_hdr *ip6, uint8_t ttl);
uint16_t get_tcp_flags(const struct tcphdr *tcp);
void apply_tcp_flags(struct tcphdr *tcp, uint16_t fl);
void extract_ports(const struct tcphdr *tcphdr, const struct udphdr *udphdr, uint8_t *proto, uint16_t *sport, uint16_t *dport);
void extract_endpoints(const struct ip *ip,const struct ip6_hdr *ip6hdr,const struct tcphdr *tcphdr,const struct udphdr *udphdr, struct sockaddr_storage *src, struct sockaddr_storage *dst);
uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind);
uint32_t *tcp_find_timestamps(struct tcphdr *tcp);
uint8_t tcp_find_scale_factor(const struct tcphdr *tcp);
uint16_t tcp_find_mss(struct tcphdr *tcp);
bool tcp_has_sack(struct tcphdr *tcp);
bool tcp_has_fastopen(const struct tcphdr *tcp);
bool ip_has_df(const struct ip *ip);
#ifdef __CYGWIN__
extern uint32_t w_win32_error;
@@ -242,15 +264,13 @@ void tcp_rewrite_winsize(struct tcphdr *tcp, uint16_t winsize, uint8_t scale_fac
typedef struct
{
uint8_t delta, min, max;
int8_t delta;
uint8_t min, max;
} autottl;
#define AUTOTTL_DEFAULT_DELTA 1
#define AUTOTTL_DEFAULT_MIN 3
#define AUTOTTL_DEFAULT_MAX 20
#define AUTOTTL_ENABLED(a) (!!(a).delta)
#define AUTOTTL_SET_DEFAULT(a) {(a).delta=AUTOTTL_DEFAULT_DELTA; (a).min=AUTOTTL_DEFAULT_MIN; (a).max=AUTOTTL_DEFAULT_MAX;}
#define AUTOTTL_ENABLED(a) ((a).delta || (a).min || (a).max)
uint8_t autottl_guess(uint8_t ttl, const autottl *attl);
uint8_t hop_count_guess(uint8_t ttl);
uint8_t autottl_eval(uint8_t hop_count, const autottl *attl);
void do_nat(bool bOutbound, struct ip *ip, struct ip6_hdr *ip6, struct tcphdr *tcphdr, struct udphdr *udphdr, const struct sockaddr_in *target4, const struct sockaddr_in6 *target6);
void verdict_tcp_csum_fix(uint8_t verdict, struct tcphdr *tcphdr, size_t transport_len, struct ip *ip, struct ip6_hdr *ip6hdr);
@@ -258,3 +278,29 @@ void verdict_udp_csum_fix(uint8_t verdict, struct udphdr *udphdr, size_t transpo
void dbgprint_socket_buffers(int fd);
bool set_socket_buffers(int fd, int rcvbuf, int sndbuf);
#ifdef HAS_FILTER_SSID
struct wlan_interface
{
int ifindex;
char ifname[IFNAMSIZ], ssid[33];
};
#define WLAN_INTERFACE_MAX 16
struct wlan_interface_collection
{
int count;
struct wlan_interface wlan[WLAN_INTERFACE_MAX];
};
extern struct wlan_interface_collection wlans;
void wlan_info_deinit(void);
bool wlan_info_init(void);
bool wlan_info_get(void);
bool wlan_info_get_rate_limited(void);
const char *wlan_ssid_search_ifname(const char *ifname);
const char *wlan_ssid_search_ifidx(int ifidx);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -32,6 +32,7 @@ enum dpi_desync_mode {
DESYNC_FAKEDDISORDER,
DESYNC_MULTISPLIT,
DESYNC_MULTIDISORDER,
DESYNC_HOSTFAKESPLIT,
DESYNC_IPFRAG2,
DESYNC_HOPBYHOP,
DESYNC_DESTOPT,
@@ -41,7 +42,7 @@ enum dpi_desync_mode {
};
extern const char *fake_http_request_default;
extern const uint8_t fake_tls_clienthello_default[648];
extern const uint8_t fake_tls_clienthello_default[680];
void randomize_default_tls_payload(uint8_t *p);
enum dpi_desync_mode desync_mode_from_string(const char *s);
@@ -52,4 +53,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);
uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifout, uint8_t *data_pkt, size_t *len_pkt);
uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifin, 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

@@ -9,6 +9,7 @@
#include <ctype.h>
#include <sys/stat.h>
#include <libgen.h>
#include <fcntl.h>
int unique_size_t(size_t *pu, int ct)
{
@@ -112,6 +113,71 @@ bool append_to_list_file(const char *filename, const char *s)
return bOK;
}
void expand_bits(void *target, const void *source, unsigned int source_bitlen, unsigned int target_bytelen)
{
unsigned int target_bitlen = target_bytelen<<3;
unsigned int bitlen = target_bitlen<source_bitlen ? target_bitlen : source_bitlen;
unsigned int bytelen = bitlen>>3;
if ((target_bytelen-bytelen)>=1) memset(target+bytelen,0,target_bytelen-bytelen);
memcpy(target,source,bytelen);
if ((bitlen &= 7)) ((uint8_t*)target)[bytelen] = ((uint8_t*)source)[bytelen] & (~((1 << (8-bitlen)) - 1));
}
// " [fd00::1]" => "fd00::1"
// "[fd00::1]:8000" => "fd00::1"
// "127.0.0.1" => "127.0.0.1"
// " 127.0.0.1:8000" => "127.0.0.1"
// " vk.com:8000" => "vk.com"
// return value: true - host is ip addr
bool strip_host_to_ip(char *host)
{
size_t l;
char *h,*p;
uint8_t addr[16];
for (h = host ; *h==' ' || *h=='\t' ; h++);
l = strlen(h);
if (l>=2)
{
if (*h=='[')
{
// ipv6 ?
for (p=++h ; *p && *p!=']' ; p++);
if (*p==']')
{
l = p-h;
memmove(host,h,l);
host[l]=0;
return inet_pton(AF_INET6, host, addr)>0;
}
}
else
{
if (inet_pton(AF_INET6, h, addr)>0)
{
// ipv6 ?
if (host!=h)
{
l = strlen(h);
memmove(host,h,l);
host[l]=0;
}
return true;
}
else
{
// ipv4 ?
for (p=h ; *p && *p!=':' ; p++);
l = p-h;
if (host!=h) memmove(host,h,l);
host[l]=0;
return inet_pton(AF_INET, host, addr)>0;
}
}
}
return false;
}
void ntop46(const struct sockaddr *sa, char *str, size_t len)
{
@@ -272,10 +338,18 @@ bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size)
return true;
}
void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize)
void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize,size_t offset)
{
size_t size;
if (offset%=patsize)
{
size = patsize-offset;
size = bufsize>size ? size : bufsize;
memcpy(buf,pattern+offset,size);
buf += size;
bufsize -= size;
}
while (bufsize)
{
size = bufsize>patsize ? patsize : bufsize;
@@ -300,6 +374,29 @@ time_t file_mod_time(const char *filename)
struct stat st;
return stat(filename,&st)==-1 ? 0 : st.st_mtime;
}
bool file_mod_signature(const char *filename, file_mod_sig *ms)
{
struct stat st;
if (stat(filename,&st)==-1)
{
FILE_MOD_RESET(ms);
return false;
}
ms->mod_time=st.st_mtime;
ms->size=st.st_size;
return true;
}
bool file_open_test(const char *filename, int flags)
{
int fd = open(filename,flags);
if (fd>=0)
{
close(fd);
return true;
}
return false;
}
bool pf_in_range(uint16_t port, const port_filter *pf)
{
@@ -367,6 +464,12 @@ void fill_random_az09(uint8_t *p,size_t sz)
}
}
void set_console_io_buffering(void)
{
setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(stderr, NULL, _IOLBF, 0);
}
bool set_env_exedir(const char *argv0)
{
char *s,*d;

View File

@@ -9,6 +9,8 @@
#include <stdio.h>
#include <time.h>
#define UNARY_PLUS(v) (v>0 ? "+" : "")
// this saves memory. sockaddr_storage is larger than required. it can be 128 bytes. sockaddr_in6 is 28 bytes.
typedef union
{
@@ -29,6 +31,10 @@ bool load_file_nonempty(const char *filename,void *buffer,size_t *buffer_size);
bool save_file(const char *filename, const void *buffer, size_t buffer_size);
bool append_to_list_file(const char *filename, const char *s);
void expand_bits(void *target, const void *source, unsigned int source_bitlen, unsigned int target_bytelen);
bool strip_host_to_ip(char *host);
void print_sockaddr(const struct sockaddr *sa);
void ntop46(const struct sockaddr *sa, char *str, size_t len);
void ntop46_port(const struct sockaddr *sa, char *str, size_t len);
@@ -51,16 +57,33 @@ 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];
}
bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size);
void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize);
void fill_pattern(uint8_t *buf,size_t bufsize,const void *pattern,size_t patsize,size_t offset);
int fprint_localtime(FILE *F);
typedef struct
{
time_t mod_time;
off_t size;
} file_mod_sig;
#define FILE_MOD_COMPARE(ms1,ms2) (((ms1)->mod_time==(ms2)->mod_time) && ((ms1)->size==(ms2)->size))
#define FILE_MOD_RESET(ms) memset(ms,0,sizeof(file_mod_sig))
bool file_mod_signature(const char *filename, file_mod_sig *ms);
time_t file_mod_time(const char *filename);
bool file_open_test(const char *filename, int flags);
typedef struct
{
@@ -75,6 +98,7 @@ void fill_random_bytes(uint8_t *p,size_t sz);
void fill_random_az(uint8_t *p,size_t sz);
void fill_random_az09(uint8_t *p,size_t sz);
void set_console_io_buffering(void);
bool set_env_exedir(const char *argv0);

View File

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

View File

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

View File

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

View File

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

400
nfq/kavl.h Normal file
View File

@@ -0,0 +1,400 @@
/* The MIT License
Copyright (c) 2018 by Attractive Chaos <attractor@live.co.uk>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/* An example:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "kavl.h"
struct my_node {
char key;
KAVL_HEAD(struct my_node) head;
};
#define my_cmp(p, q) (((q)->key < (p)->key) - ((p)->key < (q)->key))
KAVL_INIT(my, struct my_node, head, my_cmp)
int main(void) {
const char *str = "MNOLKQOPHIA"; // from wiki, except a duplicate
struct my_node *root = 0;
int i, l = strlen(str);
for (i = 0; i < l; ++i) { // insert in the input order
struct my_node *q, *p = malloc(sizeof(*p));
p->key = str[i];
q = kavl_insert(my, &root, p, 0);
if (p != q) free(p); // if already present, free
}
kavl_itr_t(my) itr;
kavl_itr_first(my, root, &itr); // place at first
do { // traverse
const struct my_node *p = kavl_at(&itr);
putchar(p->key);
free((void*)p); // free node
} while (kavl_itr_next(my, &itr));
putchar('\n');
return 0;
}
*/
#ifndef KAVL_H
#define KAVL_H
#ifdef __STRICT_ANSI__
#define inline __inline__
#endif
#define KAVL_MAX_DEPTH 64
#define kavl_size(head, p) ((p)? (p)->head.size : 0)
#define kavl_size_child(head, q, i) ((q)->head.p[(i)]? (q)->head.p[(i)]->head.size : 0)
#define KAVL_HEAD(__type) \
struct { \
__type *p[2]; \
signed char balance; /* balance factor */ \
unsigned size; /* #elements in subtree */ \
}
#define __KAVL_FIND(suf, __scope, __type, __head, __cmp) \
__scope __type *kavl_find_##suf(const __type *root, const __type *x, unsigned *cnt_) { \
const __type *p = root; \
unsigned cnt = 0; \
while (p != 0) { \
int cmp; \
cmp = __cmp(x, p); \
if (cmp >= 0) cnt += kavl_size_child(__head, p, 0) + 1; \
if (cmp < 0) p = p->__head.p[0]; \
else if (cmp > 0) p = p->__head.p[1]; \
else break; \
} \
if (cnt_) *cnt_ = cnt; \
return (__type*)p; \
}
#define __KAVL_ROTATE(suf, __type, __head) \
/* one rotation: (a,(b,c)q)p => ((a,b)p,c)q */ \
static inline __type *kavl_rotate1_##suf(__type *p, int dir) { /* dir=0 to left; dir=1 to right */ \
int opp = 1 - dir; /* opposite direction */ \
__type *q = p->__head.p[opp]; \
unsigned size_p = p->__head.size; \
p->__head.size -= q->__head.size - kavl_size_child(__head, q, dir); \
q->__head.size = size_p; \
p->__head.p[opp] = q->__head.p[dir]; \
q->__head.p[dir] = p; \
return q; \
} \
/* two consecutive rotations: (a,((b,c)r,d)q)p => ((a,b)p,(c,d)q)r */ \
static inline __type *kavl_rotate2_##suf(__type *p, int dir) { \
int b1, opp = 1 - dir; \
__type *q = p->__head.p[opp], *r = q->__head.p[dir]; \
unsigned size_x_dir = kavl_size_child(__head, r, dir); \
r->__head.size = p->__head.size; \
p->__head.size -= q->__head.size - size_x_dir; \
q->__head.size -= size_x_dir + 1; \
p->__head.p[opp] = r->__head.p[dir]; \
r->__head.p[dir] = p; \
q->__head.p[dir] = r->__head.p[opp]; \
r->__head.p[opp] = q; \
b1 = dir == 0? +1 : -1; \
if (r->__head.balance == b1) q->__head.balance = 0, p->__head.balance = -b1; \
else if (r->__head.balance == 0) q->__head.balance = p->__head.balance = 0; \
else q->__head.balance = b1, p->__head.balance = 0; \
r->__head.balance = 0; \
return r; \
}
#define __KAVL_INSERT(suf, __scope, __type, __head, __cmp) \
__scope __type *kavl_insert_##suf(__type **root_, __type *x, unsigned *cnt_) { \
unsigned char stack[KAVL_MAX_DEPTH]; \
__type *path[KAVL_MAX_DEPTH]; \
__type *bp, *bq; \
__type *p, *q, *r = 0; /* _r_ is potentially the new root */ \
int i, which = 0, top, b1, path_len; \
unsigned cnt = 0; \
bp = *root_, bq = 0; \
/* find the insertion location */ \
for (p = bp, q = bq, top = path_len = 0; p; q = p, p = p->__head.p[which]) { \
int cmp; \
cmp = __cmp(x, p); \
if (cmp >= 0) cnt += kavl_size_child(__head, p, 0) + 1; \
if (cmp == 0) { \
if (cnt_) *cnt_ = cnt; \
return p; \
} \
if (p->__head.balance != 0) \
bq = q, bp = p, top = 0; \
stack[top++] = which = (cmp > 0); \
path[path_len++] = p; \
} \
if (cnt_) *cnt_ = cnt; \
x->__head.balance = 0, x->__head.size = 1, x->__head.p[0] = x->__head.p[1] = 0; \
if (q == 0) *root_ = x; \
else q->__head.p[which] = x; \
if (bp == 0) return x; \
for (i = 0; i < path_len; ++i) ++path[i]->__head.size; \
for (p = bp, top = 0; p != x; p = p->__head.p[stack[top]], ++top) /* update balance factors */ \
if (stack[top] == 0) --p->__head.balance; \
else ++p->__head.balance; \
if (bp->__head.balance > -2 && bp->__head.balance < 2) return x; /* no re-balance needed */ \
/* re-balance */ \
which = (bp->__head.balance < 0); \
b1 = which == 0? +1 : -1; \
q = bp->__head.p[1 - which]; \
if (q->__head.balance == b1) { \
r = kavl_rotate1_##suf(bp, which); \
q->__head.balance = bp->__head.balance = 0; \
} else r = kavl_rotate2_##suf(bp, which); \
if (bq == 0) *root_ = r; \
else bq->__head.p[bp != bq->__head.p[0]] = r; \
return x; \
}
#define __KAVL_ERASE(suf, __scope, __type, __head, __cmp) \
__scope __type *kavl_erase_##suf(__type **root_, const __type *x, unsigned *cnt_) { \
__type *p, *path[KAVL_MAX_DEPTH], fake; \
unsigned char dir[KAVL_MAX_DEPTH]; \
int i, d = 0, cmp; \
unsigned cnt = 0; \
fake.__head.p[0] = *root_, fake.__head.p[1] = 0; \
if (cnt_) *cnt_ = 0; \
if (x) { \
for (cmp = -1, p = &fake; cmp; cmp = __cmp(x, p)) { \
int which = (cmp > 0); \
if (cmp > 0) cnt += kavl_size_child(__head, p, 0) + 1; \
dir[d] = which; \
path[d++] = p; \
p = p->__head.p[which]; \
if (p == 0) { \
if (cnt_) *cnt_ = 0; \
return 0; \
} \
} \
cnt += kavl_size_child(__head, p, 0) + 1; /* because p==x is not counted */ \
} else { \
for (p = &fake, cnt = 1; p; p = p->__head.p[0]) \
dir[d] = 0, path[d++] = p; \
p = path[--d]; \
} \
if (cnt_) *cnt_ = cnt; \
for (i = 1; i < d; ++i) --path[i]->__head.size; \
if (p->__head.p[1] == 0) { /* ((1,.)2,3)4 => (1,3)4; p=2 */ \
path[d-1]->__head.p[dir[d-1]] = p->__head.p[0]; \
} else { \
__type *q = p->__head.p[1]; \
if (q->__head.p[0] == 0) { /* ((1,2)3,4)5 => ((1)2,4)5; p=3 */ \
q->__head.p[0] = p->__head.p[0]; \
q->__head.balance = p->__head.balance; \
path[d-1]->__head.p[dir[d-1]] = q; \
path[d] = q, dir[d++] = 1; \
q->__head.size = p->__head.size - 1; \
} else { /* ((1,((.,2)3,4)5)6,7)8 => ((1,(2,4)5)3,7)8; p=6 */ \
__type *r; \
int e = d++; /* backup _d_ */\
for (;;) { \
dir[d] = 0; \
path[d++] = q; \
r = q->__head.p[0]; \
if (r->__head.p[0] == 0) break; \
q = r; \
} \
r->__head.p[0] = p->__head.p[0]; \
q->__head.p[0] = r->__head.p[1]; \
r->__head.p[1] = p->__head.p[1]; \
r->__head.balance = p->__head.balance; \
path[e-1]->__head.p[dir[e-1]] = r; \
path[e] = r, dir[e] = 1; \
for (i = e + 1; i < d; ++i) --path[i]->__head.size; \
r->__head.size = p->__head.size - 1; \
} \
} \
while (--d > 0) { \
__type *q = path[d]; \
int which, other, b1 = 1, b2 = 2; \
which = dir[d], other = 1 - which; \
if (which) b1 = -b1, b2 = -b2; \
q->__head.balance += b1; \
if (q->__head.balance == b1) break; \
else if (q->__head.balance == b2) { \
__type *r = q->__head.p[other]; \
if (r->__head.balance == -b1) { \
path[d-1]->__head.p[dir[d-1]] = kavl_rotate2_##suf(q, which); \
} else { \
path[d-1]->__head.p[dir[d-1]] = kavl_rotate1_##suf(q, which); \
if (r->__head.balance == 0) { \
r->__head.balance = -b1; \
q->__head.balance = b1; \
break; \
} else r->__head.balance = q->__head.balance = 0; \
} \
} \
} \
*root_ = fake.__head.p[0]; \
return p; \
}
#define kavl_free(__type, __head, __root, __free) do { \
__type *_p, *_q; \
for (_p = __root; _p; _p = _q) { \
if (_p->__head.p[0] == 0) { \
_q = _p->__head.p[1]; \
__free(_p); \
} else { \
_q = _p->__head.p[0]; \
_p->__head.p[0] = _q->__head.p[1]; \
_q->__head.p[1] = _p; \
} \
} \
} while (0)
#define __KAVL_ITR(suf, __scope, __type, __head, __cmp) \
struct kavl_itr_##suf { \
const __type *stack[KAVL_MAX_DEPTH], **top, *right; /* _right_ points to the right child of *top */ \
}; \
__scope void kavl_itr_first_##suf(const __type *root, struct kavl_itr_##suf *itr) { \
const __type *p; \
for (itr->top = itr->stack - 1, p = root; p; p = p->__head.p[0]) \
*++itr->top = p; \
itr->right = (*itr->top)->__head.p[1]; \
} \
__scope int kavl_itr_find_##suf(const __type *root, const __type *x, struct kavl_itr_##suf *itr) { \
const __type *p = root; \
itr->top = itr->stack - 1; \
while (p != 0) { \
int cmp; \
cmp = __cmp(x, p); \
if (cmp < 0) *++itr->top = p, p = p->__head.p[0]; \
else if (cmp > 0) p = p->__head.p[1]; \
else break; \
} \
if (p) { \
*++itr->top = p; \
itr->right = p->__head.p[1]; \
return 1; \
} else if (itr->top >= itr->stack) { \
itr->right = (*itr->top)->__head.p[1]; \
return 0; \
} else return 0; \
} \
__scope int kavl_itr_next_##suf(struct kavl_itr_##suf *itr) { \
for (;;) { \
const __type *p; \
for (p = itr->right, --itr->top; p; p = p->__head.p[0]) \
*++itr->top = p; \
if (itr->top < itr->stack) return 0; \
itr->right = (*itr->top)->__head.p[1]; \
return 1; \
} \
}
/**
* Insert a node to the tree
*
* @param suf name suffix used in KAVL_INIT()
* @param proot pointer to the root of the tree (in/out: root may change)
* @param x node to insert (in)
* @param cnt number of nodes smaller than or equal to _x_; can be NULL (out)
*
* @return _x_ if not present in the tree, or the node equal to x.
*/
#define kavl_insert(suf, proot, x, cnt) kavl_insert_##suf(proot, x, cnt)
/**
* Find a node in the tree
*
* @param suf name suffix used in KAVL_INIT()
* @param root root of the tree
* @param x node value to find (in)
* @param cnt number of nodes smaller than or equal to _x_; can be NULL (out)
*
* @return node equal to _x_ if present, or NULL if absent
*/
#define kavl_find(suf, root, x, cnt) kavl_find_##suf(root, x, cnt)
/**
* Delete a node from the tree
*
* @param suf name suffix used in KAVL_INIT()
* @param proot pointer to the root of the tree (in/out: root may change)
* @param x node value to delete; if NULL, delete the first node (in)
*
* @return node removed from the tree if present, or NULL if absent
*/
#define kavl_erase(suf, proot, x, cnt) kavl_erase_##suf(proot, x, cnt)
#define kavl_erase_first(suf, proot) kavl_erase_##suf(proot, 0, 0)
#define kavl_itr_t(suf) struct kavl_itr_##suf
/**
* Place the iterator at the smallest object
*
* @param suf name suffix used in KAVL_INIT()
* @param root root of the tree
* @param itr iterator
*/
#define kavl_itr_first(suf, root, itr) kavl_itr_first_##suf(root, itr)
/**
* Place the iterator at the object equal to or greater than the query
*
* @param suf name suffix used in KAVL_INIT()
* @param root root of the tree
* @param x query (in)
* @param itr iterator (out)
*
* @return 1 if find; 0 otherwise. kavl_at(itr) is NULL if and only if query is
* larger than all objects in the tree
*/
#define kavl_itr_find(suf, root, x, itr) kavl_itr_find_##suf(root, x, itr)
/**
* Move to the next object in order
*
* @param itr iterator (modified)
*
* @return 1 if there is a next object; 0 otherwise
*/
#define kavl_itr_next(suf, itr) kavl_itr_next_##suf(itr)
/**
* Return the pointer at the iterator
*
* @param itr iterator
*
* @return pointer if present; NULL otherwise
*/
#define kavl_at(itr) ((itr)->top < (itr)->stack? 0 : *(itr)->top)
#define KAVL_INIT2(suf, __scope, __type, __head, __cmp) \
__KAVL_FIND(suf, __scope, __type, __head, __cmp) \
__KAVL_ROTATE(suf, __type, __head) \
__KAVL_INSERT(suf, __scope, __type, __head, __cmp) \
__KAVL_ERASE(suf, __scope, __type, __head, __cmp) \
__KAVL_ITR(suf, __scope, __type, __head, __cmp)
#define KAVL_INIT(suf, __type, __head, __cmp) \
KAVL_INIT2(suf,, __type, __head, __cmp)
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,10 @@
#include <stdbool.h>
#ifdef __linux__
#define HAS_FILTER_SSID 1
#endif
#ifdef __CYGWIN__
extern bool bQuit;
#endif

View File

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

View File

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

View File

@@ -3,6 +3,9 @@
#include <stdarg.h>
#include <syslog.h>
#include <errno.h>
#ifdef __ANDROID__
#include <android/log.h>
#endif
#include "pools.h"
#include "desync.h"
@@ -17,6 +20,7 @@ const char *progname = "nfqws";
#error UNKNOWN_SYSTEM_TIME
#endif
const char * tld[6] = { "com","org","net","edu","gov","biz" };
int DLOG_FILE(FILE *F, const char *format, va_list args)
{
@@ -40,18 +44,47 @@ int DLOG_FILENAME(const char *filename, const char *format, va_list args)
return r;
}
static char syslog_buf[1024];
static size_t syslog_buf_sz=0;
static void syslog_buffered(int priority, const char *format, va_list args)
typedef void (*f_log_function)(int priority, const char *line);
static char log_buf[1024];
static size_t log_buf_sz=0;
static void syslog_log_function(int priority, const char *line)
{
if (vsnprintf(syslog_buf+syslog_buf_sz,sizeof(syslog_buf)-syslog_buf_sz,format,args)>0)
syslog(priority,"%s",log_buf);
}
#ifdef __ANDROID__
static enum android_LogPriority syslog_priority_to_android(int priority)
{
enum android_LogPriority ap;
switch(priority)
{
syslog_buf_sz=strlen(syslog_buf);
case LOG_INFO:
case LOG_NOTICE: ap=ANDROID_LOG_INFO; break;
case LOG_ERR: ap=ANDROID_LOG_ERROR; break;
case LOG_WARNING: ap=ANDROID_LOG_WARN; break;
case LOG_EMERG:
case LOG_ALERT:
case LOG_CRIT: ap=ANDROID_LOG_FATAL; break;
case LOG_DEBUG: ap=ANDROID_LOG_DEBUG; break;
default: ap=ANDROID_LOG_UNKNOWN;
}
return ap;
}
static void android_log_function(int priority, const char *line)
{
__android_log_print(syslog_priority_to_android(priority), progname, "%s", line);
}
#endif
static void log_buffered(f_log_function log_function, int syslog_priority, const char *format, va_list args)
{
if (vsnprintf(log_buf+log_buf_sz,sizeof(log_buf)-log_buf_sz,format,args)>0)
{
log_buf_sz=strlen(log_buf);
// log when buffer is full or buffer ends with \n
if (syslog_buf_sz>=(sizeof(syslog_buf)-1) || (syslog_buf_sz && syslog_buf[syslog_buf_sz-1]=='\n'))
if (log_buf_sz>=(sizeof(log_buf)-1) || (log_buf_sz && log_buf[log_buf_sz-1]=='\n'))
{
syslog(priority,"%s",syslog_buf);
syslog_buf_sz = 0;
log_function(syslog_priority,log_buf);
log_buf_sz = 0;
}
}
}
@@ -65,6 +98,7 @@ static int DLOG_VA(const char *format, int syslog_priority, bool condup, va_list
{
va_copy(args2,args);
DLOG_CON(format,syslog_priority,args2);
va_end(args2);
}
if (params.debug)
{
@@ -78,9 +112,16 @@ static int DLOG_VA(const char *format, int syslog_priority, bool condup, va_list
break;
case LOG_TARGET_SYSLOG:
// skip newlines
syslog_buffered(syslog_priority,format,args);
log_buffered(syslog_log_function,syslog_priority,format,args);
r = 1;
break;
#ifdef __ANDROID__
case LOG_TARGET_ANDROID:
// skip newlines
log_buffered(android_log_function,syslog_priority,format,args);
r = 1;
break;
#endif
default:
break;
}
@@ -184,34 +225,64 @@ void dp_init(struct desync_profile *dp)
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);
randomize_default_tls_payload(dp->fake_tls);
dp->fake_http_size = strlen(fake_http_request_default);
memcpy(dp->fake_http,fake_http_request_default,dp->fake_http_size);
dp->fake_quic_size = 620; // must be 601+ for TSPU hack
dp->fake_quic[0] = 0x40; // russian TSPU QUIC short header fake
dp->fake_wg_size = 64;
dp->fake_dht_size = 64;
dp->fake_unknown_size = 256;
dp->fake_syndata_size = 16;
dp->fake_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->desync_ttl6 = dp->dup_ttl6 = dp->orig_mod_ttl6 = 0xFF; // unused
dp->desync_ts_increment = dp->dup_ts_increment = TS_INCREMENT_DEFAULT;
dp->desync_badseq_increment = dp->dup_badseq_increment = BADSEQ_INCREMENT_DEFAULT;
dp->desync_badseq_ack_increment = dp->dup_badseq_ack_increment = BADSEQ_ACK_INCREMENT_DEFAULT;
dp->wssize_cutoff_mode = dp->desync_start_mode = dp->desync_cutoff_mode = dp->dup_start_mode = dp->dup_cutoff_mode = dp->orig_mod_start_mode = dp->orig_mod_cutoff_mode = 'n'; // packet number by default
dp->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;
dp->dup_ip_id_mode = IPID_SAME;
}
bool dp_fake_defaults(struct desync_profile *dp)
{
struct blob_item *item;
if (blob_collection_empty(&dp->fake_http))
if (!blob_collection_add_blob(&dp->fake_http,fake_http_request_default,strlen(fake_http_request_default),0,0))
return false;
if (blob_collection_empty(&dp->fake_tls))
{
if (!(item=blob_collection_add_blob(&dp->fake_tls,fake_tls_clienthello_default,sizeof(fake_tls_clienthello_default),4+sizeof(((struct fake_tls_mod*)0)->sni),0)))
return false;
if (!(item->extra2 = malloc(sizeof(struct fake_tls_mod))))
return false;
*(struct fake_tls_mod*)item->extra2 = dp->tls_mod_last;
}
if (blob_collection_empty(&dp->fake_unknown))
{
if (!(item=blob_collection_add_blob(&dp->fake_unknown,NULL,256,0,0)))
return false;
memset(item->data,0,item->size);
}
if (blob_collection_empty(&dp->fake_quic))
{
if (!(item=blob_collection_add_blob(&dp->fake_quic,NULL,620,0,0)))
return false;
memset(item->data,0,item->size);
item->data[0] = 0x40;
}
struct blob_collection_head **fake,*fakes_z64[] = {&dp->fake_wg, &dp->fake_dht, &dp->fake_discord, &dp->fake_stun, &dp->fake_unknown_udp,NULL};
for(fake=fakes_z64;*fake;fake++)
{
if (blob_collection_empty(*fake))
{
if (!(item=blob_collection_add_blob(*fake,NULL,64,0,0)))
return false;
memset(item->data,0,item->size);
}
}
return true;
}
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
{
struct desync_profile_list *entry = calloc(1,sizeof(struct desync_profile_list));
if (!entry) return NULL;
dp_init(&entry->dp);
// add to the tail
@@ -228,13 +299,20 @@ struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
}
static void dp_clear_dynamic(struct desync_profile *dp)
{
free(dp->fsplit_pattern);
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);
#ifdef HAS_FILTER_SSID
strlist_destroy(&dp->filter_ssid);
#endif
HostFailPoolDestroy(&dp->hostlist_auto_fail_counters);
struct blob_collection_head **fake,*fakes[] = {&dp->fake_http, &dp->fake_tls, &dp->fake_unknown, &dp->fake_unknown_udp, &dp->fake_quic, &dp->fake_wg, &dp->fake_dht, &dp->fake_discord, &dp->fake_stun, NULL};
for(fake=fakes;*fake;fake++) blob_collection_destroy(*fake);
}
void dp_clear(struct desync_profile *dp)
{
@@ -263,3 +341,42 @@ bool dp_list_have_autohostlist(struct desync_profile_list_head *head)
return true;
return false;
}
// check if we need empty outgoing ACK
bool dp_list_need_all_out(struct desync_profile_list_head *head)
{
struct desync_profile_list *dpl;
LIST_FOREACH(dpl, head, next)
if (dpl->dp.dup_repeats || PROFILE_HAS_ORIG_MOD(&dpl->dp))
return true;
return false;
}
#if !defined( __OpenBSD__) && !defined(__ANDROID__)
void cleanup_args(struct params_s *params)
{
wordfree(&params->wexp);
}
#endif
void cleanup_params(struct params_s *params)
{
#if !defined( __OpenBSD__) && !defined(__ANDROID__)
cleanup_args(params);
#endif
ConntrackPoolDestroy(&params->conntrack);
dp_list_destroy(&params->desync_profiles);
hostlist_files_destroy(&params->hostlists);
ipset_files_destroy(&params->ipsets);
ipcacheDestroy(&params->ipcache);
#ifdef __CYGWIN__
strlist_destroy(&params->ssid_filter);
strlist_destroy(&params->nlm_filter);
strlist_destroy(&params->wf_raw_part);
#else
free(params->user); params->user=NULL;
#endif
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include "nfqws.h"
#include "pools.h"
#include "conntrack.h"
#include "desync.h"
@@ -27,6 +28,8 @@
#define BADSEQ_INCREMENT_DEFAULT -10000
#define BADSEQ_ACK_INCREMENT_DEFAULT -66000
#define TS_INCREMENT_DEFAULT -600000
#define IPFRAG_UDP_DEFAULT 8
#define IPFRAG_TCP_DEFAULT 32
@@ -36,9 +39,65 @@
#define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60
#define HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT 3
#define IPCACHE_LIFETIME 7200
#define AUTOTTL_DEFAULT_DESYNC_DELTA -1
#define AUTOTTL_DEFAULT_DESYNC_MIN 3
#define AUTOTTL_DEFAULT_DESYNC_MAX 20
#define AUTOTTL_DEFAULT_ORIG_DELTA +5
#define AUTOTTL_DEFAULT_ORIG_MIN 3
#define AUTOTTL_DEFAULT_ORIG_MAX 64
#define AUTOTTL_DEFAULT_DUP_DELTA -1
#define AUTOTTL_DEFAULT_DUP_MIN 3
#define AUTOTTL_DEFAULT_DUP_MAX 64
#define MAX_SPLITS 64
enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG };
#define FAKE_TLS_MOD_SAVE_MASK 0x0F
#define FAKE_TLS_MOD_SET 0x01
#define FAKE_TLS_MOD_CUSTOM_FAKE 0x02
#define FAKE_TLS_MOD_RND 0x10
#define FAKE_TLS_MOD_DUP_SID 0x20
#define FAKE_TLS_MOD_RND_SNI 0x40
#define FAKE_TLS_MOD_SNI 0x80
#define FAKE_TLS_MOD_PADENCAP 0x100
#define FAKE_MAX_TCP 1460
#define FAKE_MAX_UDP 1472
#define MAX_GIDS 64
extern const char * tld[6];
enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG, LOG_TARGET_ANDROID };
struct fake_tls_mod_cache
{
size_t extlen_offset, padlen_offset;
};
struct fake_tls_mod
{
char sni[128];
uint32_t mod;
};
struct hostfakesplit_mod
{
char host[128];
size_t host_size;
int ordering;
};
struct fakedsplit_mod
{
int ordering;
};
struct tcp_mod
{
bool seq;
};
typedef enum {SS_NONE=0,SS_SYN,SS_SYNACK,SS_ACKSYN} t_synack_split;
typedef enum {IPID_SEQ=0,IPID_SEQ_GROUP,IPID_RND,IPID_ZERO,IPID_SAME} t_ip_id_mode;
struct desync_profile
{
@@ -47,8 +106,13 @@ struct desync_profile
uint16_t wsize,wssize;
uint8_t wscale,wsscale;
char wssize_cutoff_mode; // n - packets, d - data packets, s - relative sequence
bool wssize_no_forced_cutoff;
unsigned int wssize_cutoff;
t_synack_split synack_split;
t_ip_id_mode ip_id_mode;
bool hostcase, hostnospace, domcase, methodeol;
char hostspell[4];
enum dpi_desync_mode desync_mode0,desync_mode,desync_mode2;
@@ -58,23 +122,58 @@ struct desync_profile
// multisplit
struct proto_pos splits[MAX_SPLITS];
int split_count;
struct proto_pos seqovl;
struct proto_pos seqovl,hostfakesplit_midhost;
char dup_start_mode, dup_cutoff_mode; // n - packets, d - data packets, s - relative sequence
bool dup_replace;
unsigned int dup_start, dup_cutoff;
unsigned int dup_repeats;
uint8_t dup_ttl, dup_ttl6;
uint32_t dup_fooling_mode;
uint32_t dup_ts_increment, dup_badseq_increment, dup_badseq_ack_increment;
autottl dup_autottl, dup_autottl6;
uint16_t dup_tcp_flags_set, dup_tcp_flags_unset;
t_ip_id_mode dup_ip_id_mode;
char orig_mod_start_mode, orig_mod_cutoff_mode; // n - packets, d - data packets, s - relative sequence
unsigned int orig_mod_start, orig_mod_cutoff;
uint8_t orig_mod_ttl, orig_mod_ttl6;
autottl orig_autottl, orig_autottl6;
uint16_t orig_tcp_flags_set, orig_tcp_flags_unset;
char desync_start_mode, desync_cutoff_mode; // n - packets, d - data packets, s - relative sequence
unsigned int desync_start, desync_cutoff;
uint8_t desync_ttl, desync_ttl6;
autottl desync_autottl, desync_autottl6;
uint32_t desync_fooling_mode;
uint32_t desync_badseq_increment, desync_badseq_ack_increment;
uint8_t fake_http[1460],fake_tls[1460],fake_unknown[1460],fake_syndata[1460],seqovl_pattern[1460],fsplit_pattern[1460];
uint8_t fake_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;
uint32_t desync_ts_increment, desync_badseq_increment, desync_badseq_ack_increment;
uint16_t desync_tcp_flags_set, desync_tcp_flags_unset;
struct blob_collection_head fake_http,fake_tls,fake_unknown,fake_unknown_udp,fake_quic,fake_wg,fake_dht,fake_discord,fake_stun;
uint8_t fake_syndata[FAKE_MAX_TCP],seqovl_pattern[FAKE_MAX_TCP],udplen_pattern[FAKE_MAX_UDP];
uint8_t *fsplit_pattern;
size_t fake_syndata_size, fsplit_pattern_size;
struct fake_tls_mod tls_mod_last;
struct blob_item *tls_fake_last;
struct hostfakesplit_mod hfs_mod;
struct fakedsplit_mod fs_mod;
struct tcp_mod tcp_mod;
int udplen_increment;
bool filter_ipv4,filter_ipv6;
struct port_filters_head pf_tcp,pf_udp;
uint32_t filter_l7; // L7_PROTO_* bits
#ifdef HAS_FILTER_SSID
// per profile ssid filter
// annot use global filter because it's not possible to bind multiple instances to a single queue
// it's possible to run multiple winws instances on the same windivert filter, but it's not the case for linux
struct str_list_head filter_ssid;
#endif
// list of pointers to ipsets
struct ipset_collection_head ips_collection, ips_collection_exclude;
@@ -87,9 +186,10 @@ struct desync_profile
hostfail_pool *hostlist_auto_fail_counters;
};
#define PROFILE_IPSETS_ABSENT(dp) (!LIST_FIRST(&dp->ips_collection) && !LIST_FIRST(&dp->ips_collection_exclude))
#define PROFILE_IPSETS_EMPTY(dp) (ipset_collection_is_empty(&dp->ips_collection) && ipset_collection_is_empty(&dp->ips_collection_exclude))
#define PROFILE_HOSTLISTS_EMPTY(dp) (hostlist_collection_is_empty(&dp->hl_collection) && hostlist_collection_is_empty(&dp->hl_collection_exclude))
#define PROFILE_IPSETS_ABSENT(dp) (!LIST_FIRST(&(dp)->ips_collection) && !LIST_FIRST(&(dp)->ips_collection_exclude))
#define PROFILE_IPSETS_EMPTY(dp) (ipset_collection_is_empty(&(dp)->ips_collection) && ipset_collection_is_empty(&(dp)->ips_collection_exclude))
#define PROFILE_HOSTLISTS_EMPTY(dp) (hostlist_collection_is_empty(&(dp)->hl_collection) && hostlist_collection_is_empty(&(dp)->hl_collection_exclude))
#define PROFILE_HAS_ORIG_MOD(dp) ((dp)->orig_mod_ttl || (dp)->orig_mod_ttl6 || (dp)->orig_tcp_flags_set || (dp)->orig_tcp_flags_unset)
struct desync_profile_list {
struct desync_profile dp;
@@ -100,7 +200,9 @@ 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);
bool dp_list_need_all_out(struct desync_profile_list_head *head);
void dp_init(struct desync_profile *dp);
bool dp_fake_defaults(struct desync_profile *dp);
void dp_clear(struct desync_profile *dp);
struct params_s
@@ -113,6 +215,8 @@ struct params_s
char debug_logfile[PATH_MAX];
bool debug;
bool daemon;
#ifdef __linux__
int qnum;
#elif defined(BSD)
@@ -125,11 +229,15 @@ struct params_s
#ifdef __CYGWIN__
struct str_list_head ssid_filter,nlm_filter;
struct str_list_head wf_raw_part;
#else
bool droproot;
char *user;
uid_t uid;
gid_t gid;
gid_t gid[MAX_GIDS];
int gid_count;
#endif
char pidfile[PATH_MAX];
char hostlist_auto_debuglog[PATH_MAX];
@@ -140,10 +248,24 @@ struct params_s
unsigned int ctrack_t_syn, ctrack_t_est, ctrack_t_fin, ctrack_t_udp;
t_conntrack conntrack;
bool ctrack_disable;
bool autottl_present;
#ifdef HAS_FILTER_SSID
bool filter_ssid_present;
#endif
bool cache_hostname;
unsigned int ipcache_lifetime;
ip_cache ipcache;
};
extern struct params_s params;
extern const char *progname;
#if !defined( __OpenBSD__) && !defined(__ANDROID__)
void cleanup_args(struct params_s *params);
#endif
void cleanup_params(struct params_s *params);
int DLOG(const char *format, ...);
int DLOG_ERR(const char *format, ...);

View File

@@ -3,6 +3,7 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <arpa/inet.h>
#define DESTROY_STR_POOL(etype, ppool) \
etype *elem, *tmp; \
@@ -11,7 +12,7 @@
HASH_DEL(*ppool, elem); \
free(elem); \
}
#define ADD_STR_POOL(etype, ppool, keystr, keystr_len) \
etype *elem; \
if (!(elem = (etype*)malloc(sizeof(etype)))) \
@@ -24,14 +25,20 @@
memcpy(elem->str, keystr, keystr_len); \
elem->str[keystr_len] = 0; \
oom = false; \
HASH_ADD_KEYPTR(hh, *ppool, elem->str, strlen(elem->str), elem); \
HASH_ADD_KEYPTR(hh, *ppool, elem->str, keystr_len, elem); \
if (oom) \
{ \
free(elem->str); \
free(elem); \
return false; \
}
#define ADD_HOSTLIST_POOL(etype, ppool, keystr, keystr_len, flg) \
etype *elem_find; \
HASH_FIND(hh, *ppool, keystr, keystr_len, elem_find); \
if (!elem_find) { \
ADD_STR_POOL(etype,ppool,keystr,keystr_len); \
elem->flags = flg; \
}
#undef uthash_nonfatal_oom
#define uthash_nonfatal_oom(elt) ut_oom_recover(elt)
@@ -42,27 +49,31 @@ static void ut_oom_recover(void *elem)
}
// for not zero terminated strings
bool StrPoolAddStrLen(strpool **pp, const char *s, size_t slen)
bool HostlistPoolAddStrLen(hostlist_pool **pp, const char *s, size_t slen, uint32_t flags)
{
ADD_STR_POOL(strpool, pp, s, slen)
ADD_HOSTLIST_POOL(hostlist_pool, pp, s, slen, flags)
return true;
}
// for zero terminated strings
bool StrPoolAddStr(strpool **pp, const char *s)
bool HostlistPoolAddStr(hostlist_pool **pp, const char *s, uint32_t flags)
{
return StrPoolAddStrLen(pp, s, strlen(s));
return HostlistPoolAddStrLen(pp, s, strlen(s), flags);
}
bool StrPoolCheckStr(strpool *p, const char *s)
hostlist_pool *HostlistPoolGetStr(hostlist_pool *p, const char *s)
{
strpool *elem;
hostlist_pool *elem;
HASH_FIND_STR(p, s, elem);
return elem != NULL;
return elem;
}
bool HostlistPoolCheckStr(hostlist_pool *p, const char *s)
{
return !!HostlistPoolGetStr(p,s);
}
void StrPoolDestroy(strpool **pp)
void HostlistPoolDestroy(hostlist_pool **pp)
{
DESTROY_STR_POOL(strpool, pp)
DESTROY_STR_POOL(hostlist_pool, pp)
}
@@ -139,7 +150,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)
@@ -151,7 +162,19 @@ void strlist_destroy(struct str_list_head *head)
strlist_entry_destroy(entry);
}
}
bool strlist_search(const struct str_list_head *head, const char *str)
{
struct str_list *entry;
if (str)
{
LIST_FOREACH(entry, head, next)
{
if (!strcmp(entry->str, str))
return true;
}
}
return false;
}
@@ -170,7 +193,7 @@ struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const
}
else
entry->filename = NULL;
entry->mod_time = 0;
FILE_MOD_RESET(&entry->mod_sig);
entry->hostlist = NULL;
LIST_INSERT_HEAD(head, entry, next);
}
@@ -178,8 +201,8 @@ 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);
StrPoolDestroy(&entry->hostlist);
free(entry->filename);
HostlistPoolDestroy(&entry->hostlist);
free(entry);
}
void hostlist_files_destroy(struct hostlist_files_head *head)
@@ -202,6 +225,13 @@ struct hostlist_file *hostlist_files_search(struct hostlist_files_head *head, co
}
return NULL;
}
void hostlist_files_reset_modtime(struct hostlist_files_head *list)
{
struct hostlist_file *hfile;
LIST_FOREACH(hfile, list, next)
FILE_MOD_RESET(&hfile->mod_sig);
}
struct hostlist_item *hostlist_collection_add(struct hostlist_collection_head *head, struct hostlist_file *hfile)
{
@@ -246,121 +276,146 @@ bool hostlist_collection_is_empty(const struct hostlist_collection_head *head)
}
void ipset4Destroy(ipset4 **ipset)
static int kavl_bit_cmp(const struct kavl_bit_elem *p, const struct kavl_bit_elem *q)
{
ipset4 *elem, *tmp;
HASH_ITER(hh, *ipset, elem, tmp)
unsigned int bitlen = q->bitlen < p->bitlen ? q->bitlen : p->bitlen;
unsigned int df = bitlen & 7, bytes = bitlen >> 3;
int cmp = memcmp(p->data, q->data, bytes);
if (cmp || !df) return cmp;
uint8_t c1 = p->data[bytes] >> (8 - df);
uint8_t c2 = q->data[bytes] >> (8 - df);
return c1<c2 ? -1 : c1==c2 ? 0 : 1;
}
KAVL_INIT(kavl_bit, struct kavl_bit_elem, head, kavl_bit_cmp)
static void kavl_bit_destroy_elem(struct kavl_bit_elem *e)
{
if (e)
{
HASH_DEL(*ipset, elem);
free(elem);
free(e->data);
free(e);
}
}
bool ipset4Check(ipset4 *ipset, const struct in_addr *a, uint8_t preflen)
void kavl_bit_delete(struct kavl_bit_elem **hdr, const void *data, unsigned int bitlen)
{
uint32_t ip = ntohl(a->s_addr);
struct cidr4 cidr;
ipset4 *ips_found;
// zero alignment bytes
memset(&cidr,0,sizeof(cidr));
cidr.preflen = preflen+1;
do
{
cidr.preflen--;
cidr.addr.s_addr = htonl(ip & mask_from_preflen(cidr.preflen));
HASH_FIND(hh, ipset, &cidr, sizeof(cidr), ips_found);
if (ips_found) return true;
} while(cidr.preflen);
return false;
struct kavl_bit_elem temp = {
.bitlen = bitlen, .data = (uint8_t*)data
};
kavl_bit_destroy_elem(kavl_erase(kavl_bit, hdr, &temp, 0));
}
bool ipset4Add(ipset4 **ipset, const struct in_addr *a, uint8_t preflen)
void kavl_bit_destroy(struct kavl_bit_elem **hdr)
{
while (*hdr)
{
struct kavl_bit_elem *e = kavl_erase_first(kavl_bit, hdr);
if (!e) break;
kavl_bit_destroy_elem(e);
}
free(*hdr);
}
struct kavl_bit_elem *kavl_bit_add(struct kavl_bit_elem **hdr, void *data, unsigned int bitlen, size_t struct_size)
{
if (!struct_size) struct_size=sizeof(struct kavl_bit_elem);
struct kavl_bit_elem *v, *e = calloc(1, struct_size);
if (!e) return 0;
e->bitlen = bitlen;
e->data = data;
v = kavl_insert(kavl_bit, hdr, e, 0);
while (e != v && e->bitlen < v->bitlen)
{
kavl_bit_delete(hdr, v->data, v->bitlen);
v = kavl_insert(kavl_bit, hdr, e, 0);
}
if (e != v) kavl_bit_destroy_elem(e);
return v;
}
struct kavl_bit_elem *kavl_bit_get(const struct kavl_bit_elem *hdr, const void *data, unsigned int bitlen)
{
struct kavl_bit_elem temp = {
.bitlen = bitlen, .data = (uint8_t*)data
};
return kavl_find(kavl_bit, hdr, &temp, 0);
}
static bool ipset_kavl_add(struct kavl_bit_elem **ipset, const void *a, uint8_t preflen)
{
uint8_t bytelen = (preflen+7)>>3;
uint8_t *abuf = malloc(bytelen);
if (!abuf) return false;
memcpy(abuf,a,bytelen);
if (!kavl_bit_add(ipset,abuf,preflen,0))
{
free(abuf);
return false;
}
return true;
}
bool ipset4Check(const struct kavl_bit_elem *ipset, const struct in_addr *a, uint8_t preflen)
{
return !!kavl_bit_get(ipset,a,preflen);
}
bool ipset4Add(struct kavl_bit_elem **ipset, const struct in_addr *a, uint8_t preflen)
{
if (preflen>32) return false;
// avoid dups
if (ipset4Check(*ipset, a, preflen)) return true; // already included
struct ipset4 *entry = calloc(1,sizeof(ipset4));
if (!entry) return false;
entry->cidr.addr.s_addr = htonl(ntohl(a->s_addr) & mask_from_preflen(preflen));
entry->cidr.preflen = preflen;
oom = false;
HASH_ADD(hh, *ipset, cidr, sizeof(entry->cidr), entry);
if (oom) { free(entry); return false; }
return true;
return ipset_kavl_add(ipset,a,preflen);
}
void ipset4Print(ipset4 *ipset)
void ipset4Print(struct kavl_bit_elem *ipset)
{
ipset4 *ips, *tmp;
HASH_ITER(hh, ipset , ips, tmp)
{
print_cidr4(&ips->cidr);
printf("\n");
}
}
if (!ipset) return;
void ipset6Destroy(ipset6 **ipset)
{
ipset6 *elem, *tmp;
HASH_ITER(hh, *ipset, elem, tmp)
{
HASH_DEL(*ipset, elem);
free(elem);
}
}
bool ipset6Check(ipset6 *ipset, const struct in6_addr *a, uint8_t preflen)
{
struct cidr6 cidr;
ipset6 *ips_found;
// zero alignment bytes
memset(&cidr,0,sizeof(cidr));
cidr.preflen = preflen+1;
struct cidr4 c;
const struct kavl_bit_elem *elem;
kavl_itr_t(kavl_bit) itr;
kavl_itr_first(kavl_bit, ipset, &itr);
do
{
cidr.preflen--;
ip6_and(a, mask_from_preflen6(cidr.preflen), &cidr.addr);
HASH_FIND(hh, ipset, &cidr, sizeof(cidr), ips_found);
if (ips_found) return true;
} while(cidr.preflen);
return false;
}
bool ipset6Add(ipset6 **ipset, const struct in6_addr *a, uint8_t preflen)
{
if (preflen>128) return false;
// avoid dups
if (ipset6Check(*ipset, a, preflen)) return true; // already included
struct ipset6 *entry = calloc(1,sizeof(ipset6));
if (!entry) return false;
ip6_and(a, mask_from_preflen6(preflen), &entry->cidr.addr);
entry->cidr.preflen = preflen;
oom = false;
HASH_ADD(hh, *ipset, cidr, sizeof(entry->cidr), entry);
if (oom) { free(entry); return false; }
return true;
}
void ipset6Print(ipset6 *ipset)
{
ipset6 *ips, *tmp;
HASH_ITER(hh, ipset , ips, tmp)
{
print_cidr6(&ips->cidr);
elem = kavl_at(&itr);
c.preflen = elem->bitlen;
expand_bits(&c.addr, elem->data, elem->bitlen, sizeof(c.addr));
print_cidr4(&c);
printf("\n");
}
while (kavl_itr_next(kavl_bit, &itr));
}
bool ipset6Check(const struct kavl_bit_elem *ipset, const struct in6_addr *a, uint8_t preflen)
{
return !!kavl_bit_get(ipset,a,preflen);
}
bool ipset6Add(struct kavl_bit_elem **ipset, const struct in6_addr *a, uint8_t preflen)
{
if (preflen>128) return false;
return ipset_kavl_add(ipset,a,preflen);
}
void ipset6Print(struct kavl_bit_elem *ipset)
{
if (!ipset) return;
struct cidr6 c;
const struct kavl_bit_elem *elem;
kavl_itr_t(kavl_bit) itr;
kavl_itr_first(kavl_bit, ipset, &itr);
do
{
elem = kavl_at(&itr);
c.preflen = elem->bitlen;
expand_bits(&c.addr, elem->data, elem->bitlen, sizeof(c.addr));
print_cidr6(&c);
printf("\n");
}
while (kavl_itr_next(kavl_bit, &itr));
}
void ipsetDestroy(ipset *ipset)
{
ipset4Destroy(&ipset->ips4);
ipset6Destroy(&ipset->ips6);
kavl_bit_destroy(&ipset->ips4);
kavl_bit_destroy(&ipset->ips6);
}
void ipsetPrint(ipset *ipset)
{
@@ -384,7 +439,7 @@ struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *fi
}
else
entry->filename = NULL;
entry->mod_time = 0;
FILE_MOD_RESET(&entry->mod_sig);
memset(&entry->ipset,0,sizeof(entry->ipset));
LIST_INSERT_HEAD(head, entry, next);
}
@@ -392,7 +447,7 @@ struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *fi
}
static void ipset_files_entry_destroy(struct ipset_file *entry)
{
if (entry->filename) free(entry->filename);
free(entry->filename);
ipsetDestroy(&entry->ipset);
free(entry);
}
@@ -416,6 +471,13 @@ struct ipset_file *ipset_files_search(struct ipset_files_head *head, const char
}
return NULL;
}
void ipset_files_reset_modtime(struct ipset_files_head *list)
{
struct ipset_file *hfile;
LIST_FOREACH(hfile, list, next)
FILE_MOD_RESET(&hfile->mod_sig);
}
struct ipset_item *ipset_collection_add(struct ipset_collection_head *head, struct ipset_file *hfile)
{
@@ -497,3 +559,284 @@ bool port_filters_deny_if_empty(struct port_filters_head *head)
if (LIST_FIRST(head)) return true;
return pf_parse("0",&pf) && port_filter_add(head,&pf);
}
struct blob_item *blob_collection_add(struct blob_collection_head *head)
{
struct blob_item *entry = calloc(1,sizeof(struct blob_item));
if (entry)
{
// insert to the end
struct blob_item *itemc,*iteml=LIST_FIRST(head);
if (iteml)
{
while ((itemc=LIST_NEXT(iteml,next))) iteml = itemc;
LIST_INSERT_AFTER(iteml, entry, next);
}
else
LIST_INSERT_HEAD(head, entry, next);
}
return entry;
}
struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, const void *data, size_t size, size_t size_reserve, size_t offset)
{
if (offset>=size) return NULL;
struct blob_item *entry = calloc(1,sizeof(struct blob_item));
if (!entry) return NULL;
if (!(entry->data = malloc(size+size_reserve)))
{
free(entry);
return NULL;
}
if (data) memcpy(entry->data,data,size);
entry->size = size;
entry->size_buf = size+size_reserve;
entry->offset = offset;
// insert to the end
struct blob_item *itemc,*iteml=LIST_FIRST(head);
if (iteml)
{
while ((itemc=LIST_NEXT(iteml,next))) iteml = itemc;
LIST_INSERT_AFTER(iteml, entry, next);
}
else
LIST_INSERT_HEAD(head, entry, next);
return entry;
}
void blob_collection_destroy(struct blob_collection_head *head)
{
struct blob_item *entry;
while ((entry = LIST_FIRST(head)))
{
LIST_REMOVE(entry, next);
free(entry->extra);
free(entry->extra2);
free(entry->data);
free(entry);
}
}
bool blob_collection_empty(const struct blob_collection_head *head)
{
return !LIST_FIRST(head);
}
static void ipcache_item_touch(ip_cache_item *item)
{
time(&item->last);
}
static void ipcache_item_init(ip_cache_item *item)
{
ipcache_item_touch(item);
item->hostname = NULL;
item->hostname_is_ip = false;
item->hops = 0;
}
static void ipcache_item_destroy(ip_cache_item *item)
{
free(item->hostname);
}
static void ipcache4Destroy(ip_cache4 **ipcache)
{
ip_cache4 *elem, *tmp;
HASH_ITER(hh, *ipcache, elem, tmp)
{
HASH_DEL(*ipcache, elem);
ipcache_item_destroy(&elem->data);
free(elem);
}
}
static void ipcache4Key(ip4if *key, const struct in_addr *a, const char *iface)
{
memset(key,0,sizeof(*key)); // make sure everything is zero
key->addr = *a;
if (iface) snprintf(key->iface,sizeof(key->iface),"%s",iface);
}
static ip_cache4 *ipcache4Find(ip_cache4 *ipcache, const struct in_addr *a, const char *iface)
{
ip_cache4 *entry;
struct ip4if key;
ipcache4Key(&key,a,iface);
HASH_FIND(hh, ipcache, &key, sizeof(key), entry);
return entry;
}
static ip_cache4 *ipcache4Add(ip_cache4 **ipcache, const struct in_addr *a, const char *iface)
{
// avoid dups
ip_cache4 *entry = ipcache4Find(*ipcache,a,iface);
if (entry) return entry; // already included
entry = malloc(sizeof(ip_cache4));
if (!entry) return NULL;
ipcache4Key(&entry->key,a,iface);
oom = false;
HASH_ADD(hh, *ipcache, key, sizeof(entry->key), entry);
if (oom) { free(entry); return NULL; }
ipcache_item_init(&entry->data);
return entry;
}
static void ipcache4Print(ip_cache4 *ipcache)
{
char s_ip[16];
time_t now;
ip_cache4 *ipc, *tmp;
time(&now);
HASH_ITER(hh, ipcache , ipc, tmp)
{
*s_ip=0;
inet_ntop(AF_INET, &ipc->key.addr, s_ip, sizeof(s_ip));
printf("%s iface=%s : hops %u hostname=%s hostname_is_ip=%u now=last+%llu\n", s_ip, ipc->key.iface, ipc->data.hops, ipc->data.hostname ? ipc->data.hostname : "", ipc->data.hostname_is_ip, (unsigned long long)(now-ipc->data.last));
}
}
static void ipcache6Destroy(ip_cache6 **ipcache)
{
ip_cache6 *elem, *tmp;
HASH_ITER(hh, *ipcache, elem, tmp)
{
HASH_DEL(*ipcache, elem);
ipcache_item_destroy(&elem->data);
free(elem);
}
}
static void ipcache6Key(ip6if *key, const struct in6_addr *a, const char *iface)
{
memset(key,0,sizeof(*key)); // make sure everything is zero
key->addr = *a;
if (iface) snprintf(key->iface,sizeof(key->iface),"%s",iface);
}
static ip_cache6 *ipcache6Find(ip_cache6 *ipcache, const struct in6_addr *a, const char *iface)
{
ip_cache6 *entry;
ip6if key;
ipcache6Key(&key,a,iface);
HASH_FIND(hh, ipcache, &key, sizeof(key), entry);
return entry;
}
static ip_cache6 *ipcache6Add(ip_cache6 **ipcache, const struct in6_addr *a, const char *iface)
{
// avoid dups
ip_cache6 *entry = ipcache6Find(*ipcache,a,iface);
if (entry) return entry; // already included
entry = malloc(sizeof(ip_cache6));
if (!entry) return NULL;
ipcache6Key(&entry->key,a,iface);
oom = false;
HASH_ADD(hh, *ipcache, key, sizeof(entry->key), entry);
if (oom) { free(entry); return NULL; }
ipcache_item_init(&entry->data);
return entry;
}
static void ipcache6Print(ip_cache6 *ipcache)
{
char s_ip[40];
time_t now;
ip_cache6 *ipc, *tmp;
time(&now);
HASH_ITER(hh, ipcache , ipc, tmp)
{
*s_ip=0;
inet_ntop(AF_INET6, &ipc->key.addr, s_ip, sizeof(s_ip));
printf("%s iface=%s : hops %u hostname=%s hostname_is_ip=%u now=last+%llu\n", s_ip, ipc->key.iface, ipc->data.hops, ipc->data.hostname ? ipc->data.hostname : "", ipc->data.hostname_is_ip, (unsigned long long)(now-ipc->data.last));
}
}
void ipcacheDestroy(ip_cache *ipcache)
{
ipcache4Destroy(&ipcache->ipcache4);
ipcache6Destroy(&ipcache->ipcache6);
}
void ipcachePrint(ip_cache *ipcache)
{
ipcache4Print(ipcache->ipcache4);
ipcache6Print(ipcache->ipcache6);
}
ip_cache_item *ipcacheTouch(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6, const char *iface)
{
ip_cache4 *ipcache4;
ip_cache6 *ipcache6;
if (a4)
{
if ((ipcache4 = ipcache4Add(&ipcache->ipcache4,a4,iface)))
{
ipcache_item_touch(&ipcache4->data);
return &ipcache4->data;
}
}
else if (a6)
{
if ((ipcache6 = ipcache6Add(&ipcache->ipcache6,a6,iface)))
{
ipcache_item_touch(&ipcache6->data);
return &ipcache6->data;
}
}
return NULL;
}
static void ipcache4_purge(ip_cache4 **ipcache, time_t lifetime)
{
ip_cache4 *elem, *tmp;
time_t now = time(NULL);
HASH_ITER(hh, *ipcache, elem, tmp)
{
if (now >= (elem->data.last + lifetime))
{
HASH_DEL(*ipcache, elem);
ipcache_item_destroy(&elem->data);
free(elem);
}
}
}
static void ipcache6_purge(ip_cache6 **ipcache, time_t lifetime)
{
ip_cache6 *elem, *tmp;
time_t now = time(NULL);
HASH_ITER(hh, *ipcache, elem, tmp)
{
if (now >= (elem->data.last + lifetime))
{
HASH_DEL(*ipcache, elem);
ipcache_item_destroy(&elem->data);
free(elem);
}
}
}
static void ipcache_purge(ip_cache *ipcache, time_t lifetime)
{
if (lifetime) // 0 = no expire
{
ipcache4_purge(&ipcache->ipcache4, lifetime);
ipcache6_purge(&ipcache->ipcache6, lifetime);
}
}
static time_t ipcache_purge_prev=0;
void ipcachePurgeRateLimited(ip_cache *ipcache, time_t lifetime)
{
time_t now = time(NULL);
// do not purge too often to save resources
if (ipcache_purge_prev != now)
{
ipcache_purge(ipcache, lifetime);
ipcache_purge_prev = now;
}
}

View File

@@ -3,6 +3,7 @@
#include <stdbool.h>
#include <ctype.h>
#include <sys/queue.h>
#include <net/if.h>
#include <time.h>
#include "helpers.h"
@@ -12,15 +13,20 @@
#define HASH_FUNCTION HASH_BER
#include "uthash.h"
typedef struct strpool {
char *str; /* key */
UT_hash_handle hh; /* makes this structure hashable */
} strpool;
#include "kavl.h"
void StrPoolDestroy(strpool **pp);
bool StrPoolAddStr(strpool **pp,const char *s);
bool StrPoolAddStrLen(strpool **pp,const char *s,size_t slen);
bool StrPoolCheckStr(strpool *p,const char *s);
#define HOSTLIST_POOL_FLAG_STRICT_MATCH 1
typedef struct hostlist_pool {
char *str; /* key */
uint32_t flags; /* custom data */
UT_hash_handle hh; /* makes this structure hashable */
} hostlist_pool;
void HostlistPoolDestroy(hostlist_pool **pp);
bool HostlistPoolAddStr(hostlist_pool **pp, const char *s, uint32_t flags);
bool HostlistPoolAddStrLen(hostlist_pool **pp, const char *s, size_t slen, uint32_t flags);
hostlist_pool *HostlistPoolGetStr(hostlist_pool *p, const char *s);
struct str_list {
char *str;
@@ -28,11 +34,16 @@ struct str_list {
};
LIST_HEAD(str_list_head, str_list);
bool strlist_add(struct str_list_head *head, const char *filename);
void strlist_destroy(struct str_list_head *head);
bool strlist_search(const struct str_list_head *head, const char *str);
typedef struct hostfail_pool {
char *str; /* key */
int counter; /* value */
time_t expire; /* when to expire record (unixtime) */
UT_hash_handle hh; /* makes this structure hashable */
char *str; /* key */
int counter; /* value */
time_t expire; /* when to expire record (unixtime) */
UT_hash_handle hh; /* makes this structure hashable */
} hostfail_pool;
void HostFailPoolDestroy(hostfail_pool **pp);
@@ -43,15 +54,11 @@ void HostFailPoolPurge(hostfail_pool **pp);
void HostFailPoolPurgeRateLimited(hostfail_pool **pp);
void HostFailPoolDump(hostfail_pool *p);
bool strlist_add(struct str_list_head *head, const char *filename);
void strlist_destroy(struct str_list_head *head);
struct hostlist_file {
char *filename;
time_t mod_time;
strpool *hostlist;
file_mod_sig mod_sig;
hostlist_pool *hostlist;
LIST_ENTRY(hostlist_file) next;
};
LIST_HEAD(hostlist_files_head, hostlist_file);
@@ -59,6 +66,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;
@@ -71,39 +79,40 @@ struct hostlist_item *hostlist_collection_search(struct hostlist_collection_head
bool hostlist_collection_is_empty(const struct hostlist_collection_head *head);
typedef struct ipset4 {
struct cidr4 cidr; /* key */
UT_hash_handle hh; /* makes this structure hashable */
} ipset4;
typedef struct ipset6 {
struct cidr6 cidr; /* key */
UT_hash_handle hh; /* makes this structure hashable */
} ipset6;
struct kavl_bit_elem
{
unsigned int bitlen;
uint8_t *data;
KAVL_HEAD(struct kavl_bit_elem) head;
};
struct kavl_bit_elem *kavl_bit_get(const struct kavl_bit_elem *hdr, const void *data, unsigned int bitlen);
struct kavl_bit_elem *kavl_bit_add(struct kavl_bit_elem **hdr, void *data, unsigned int bitlen, size_t struct_size);
void kavl_bit_delete(struct kavl_bit_elem **hdr, const void *data, unsigned int bitlen);
void kavl_bit_destroy(struct kavl_bit_elem **hdr);
// combined ipset ipv4 and ipv6
typedef struct ipset {
ipset4 *ips4;
ipset6 *ips6;
struct kavl_bit_elem *ips4,*ips6;
} ipset;
#define IPSET_EMPTY(ips) (!(ips)->ips4 && !(ips)->ips6)
void ipset4Destroy(ipset4 **ipset);
bool ipset4Add(ipset4 **ipset, const struct in_addr *a, uint8_t preflen);
static inline bool ipset4AddCidr(ipset4 **ipset, const struct cidr4 *cidr)
bool ipset4Add(struct kavl_bit_elem **ipset, const struct in_addr *a, uint8_t preflen);
static inline bool ipset4AddCidr(struct kavl_bit_elem **ipset, const struct cidr4 *cidr)
{
return ipset4Add(ipset,&cidr->addr,cidr->preflen);
}
bool ipset4Check(ipset4 *ipset, const struct in_addr *a, uint8_t preflen);
void ipset4Print(ipset4 *ipset);
bool ipset4Check(const struct kavl_bit_elem *ipset, const struct in_addr *a, uint8_t preflen);
void ipset4Print(struct kavl_bit_elem *ipset);
void ipset6Destroy(ipset6 **ipset);
bool ipset6Add(ipset6 **ipset, const struct in6_addr *a, uint8_t preflen);
static inline bool ipset6AddCidr(ipset6 **ipset, const struct cidr6 *cidr)
bool ipset6Add(struct kavl_bit_elem **ipset, const struct in6_addr *a, uint8_t preflen);
static inline bool ipset6AddCidr(struct kavl_bit_elem **ipset, const struct cidr6 *cidr)
{
return ipset6Add(ipset,&cidr->addr,cidr->preflen);
}
bool ipset6Check(ipset6 *ipset, const struct in6_addr *a, uint8_t preflen);
void ipset6Print(ipset6 *ipset);
bool ipset6Check(const struct kavl_bit_elem *ipset, const struct in6_addr *a, uint8_t preflen);
void ipset6Print(struct kavl_bit_elem *ipset);
void ipsetDestroy(ipset *ipset);
void ipsetPrint(ipset *ipset);
@@ -111,7 +120,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 +129,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;
@@ -141,3 +151,60 @@ bool port_filter_add(struct port_filters_head *head, const port_filter *pf);
void port_filters_destroy(struct port_filters_head *head);
bool port_filters_in_range(const struct port_filters_head *head, uint16_t port);
bool port_filters_deny_if_empty(struct port_filters_head *head);
struct blob_item {
uint8_t *data; // main data blob
size_t size; // main data blob size
size_t size_buf;// main data blob allocated size
size_t offset; // optional offset to useful data
void *extra; // any data without size
void *extra2; // any data without size
LIST_ENTRY(blob_item) next;
};
LIST_HEAD(blob_collection_head, blob_item);
struct blob_item *blob_collection_add(struct blob_collection_head *head);
struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, const void *data, size_t size, size_t size_reserve, size_t offset);
void blob_collection_destroy(struct blob_collection_head *head);
bool blob_collection_empty(const struct blob_collection_head *head);
typedef struct ip4if
{
char iface[IFNAMSIZ];
struct in_addr addr;
} ip4if;
typedef struct ip6if
{
char iface[IFNAMSIZ];
struct in6_addr addr;
} ip6if;
typedef struct ip_cache_item
{
time_t last;
char *hostname;
bool hostname_is_ip;
uint8_t hops;
} ip_cache_item;
typedef struct ip_cache4
{
ip4if key;
ip_cache_item data;
UT_hash_handle hh; /* makes this structure hashable */
} ip_cache4;
typedef struct ip_cache6
{
ip6if key;
ip_cache_item data;
UT_hash_handle hh; /* makes this structure hashable */
} ip_cache6;
typedef struct ip_cache
{
ip_cache4 *ipcache4;
ip_cache6 *ipcache6;
} ip_cache;
ip_cache_item *ipcacheTouch(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6, const char *iface);
void ipcachePurgeRateLimited(ip_cache *ipcache, time_t lifetime);
void ipcacheDestroy(ip_cache *ipcache);
void ipcachePrint(ip_cache *ipcache);

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