Template
1
0
mirror of https://github.com/bol-van/zapret2.git synced 2026-03-14 06:13:09 +00:00

591 Commits
v0.5 ... v0.8.4

Author SHA1 Message Date
bol-van
7c320c8d57 update docs 2026-01-12 10:13:26 +03:00
bol-van
b18f0770c8 update docs 2026-01-12 10:12:35 +03:00
bol-van
f7fc845014 update docs 2026-01-12 10:11:10 +03:00
bol-van
2c1a885a07 update docs 2026-01-12 10:10:01 +03:00
bol-van
9eb308d84c update docs 2026-01-12 10:09:02 +03:00
bol-van
3e724c3810 update docs 2026-01-12 10:03:35 +03:00
bol-van
c179d55d88 nfqws2: harden wireguard detector 2026-01-12 09:34:56 +03:00
bol-van
3f1af1441e nfqws2: check quit flag outside of EINTR context 2026-01-12 09:08:19 +03:00
bol-van
4c1b2b65f3 nfqws2: gracefully shutdown on SIGINT and SIGTERM 2026-01-11 21:01:18 +03:00
bol-van
918258413f nfqws2: fix tls reasm logic 2026-01-11 19:41:13 +03:00
bol-van
e6206c5a5f nfqws2: fix tls reasm 2026-01-11 18:20:29 +03:00
bol-van
f93c6de772 nfqws2: --payload-disable 2026-01-11 17:25:53 +03:00
bol-van
5a7e2b1ca2 nfqws2: alternative representation of payload filter in execution_plan item 2026-01-11 16:20:45 +03:00
bol-van
ca8104c72a zapret-lib: remove bitable, use barray 2026-01-11 15:36:10 +03:00
bol-van
3aad1f9ed9 nfqws2: optimize ctx userdata 2026-01-11 14:10:42 +03:00
bol-van
fd288d5e7d nfqws2: move ctx from lightuserdata to userdata. prevents crashes on specific ARM cpus 2026-01-11 13:58:31 +03:00
bol-van
349fe3f7d7 update docs 2026-01-11 12:32:44 +03:00
bol-van
4554b7c15b zapret-lib, zapret-antidpi: use numeric indexes in http dissects 2026-01-11 12:29:53 +03:00
bol-van
0b595ae3a8 AI inspired fixes 2026-01-11 11:39:37 +03:00
bol-van
3e69e1b8c1 zapret-lib: bitable 2026-01-11 11:21:12 +03:00
bol-van
02b895910b dvtws2: openbsd compile fix 2026-01-11 11:04:09 +03:00
bol-van
b2a53e9c64 nfqws2: AI inspired fixes 2026-01-11 10:56:24 +03:00
bol-van
a626cfce8a update docs 2026-01-11 09:36:47 +03:00
bol-van
ebcbfc37ba update docs 2026-01-10 20:14:44 +03:00
bol-van
33d3c94b68 update docs 2026-01-10 20:12:45 +03:00
bol-van
d55dbb7717 update docs 2026-01-10 20:05:21 +03:00
bol-van
cb82be9eab update docs 2026-01-10 20:04:01 +03:00
bol-van
024d36acc4 update docs 2026-01-10 20:02:06 +03:00
bol-van
08c6151a4c update docs 2026-01-10 19:56:22 +03:00
bol-van
520317dc3c update docs 2026-01-10 19:24:02 +03:00
bol-van
6bc0bf1b97 AI inspired fixes 2026-01-10 18:54:26 +03:00
bol-van
d18fec9053 update docs 2026-01-10 16:47:40 +03:00
bol-van
e60e5a0578 update docs 2026-01-10 16:46:44 +03:00
bol-van
84576a7039 update docs 2026-01-10 16:44:07 +03:00
bol-van
7957a0a425 update docs 2026-01-10 16:42:58 +03:00
bol-van
7ba4110416 update docs 2026-01-10 16:35:54 +03:00
bol-van
4babaef6a8 update docs 2026-01-10 16:32:54 +03:00
bol-van
872e37d160 update docs 2026-01-10 16:28:48 +03:00
bol-van
a8219f4897 update docs 2026-01-10 16:25:24 +03:00
bol-van
36267b7e9b update docs 2026-01-10 16:22:35 +03:00
bol-van
99a7f06976 eng manual 2026-01-10 15:42:42 +03:00
bol-van
3617b8934f blockcheck2: 23-seqovl fix 2026-01-10 14:58:38 +03:00
bol-van
8e6387a6df config.default add MDIG comments 2026-01-09 13:14:36 +03:00
bol-van
3bc0e8e350 mdig: EAGAIN->EAI_AGAIN help text 2026-01-09 12:38:06 +03:00
bol-van
7f12334872 update docs 2026-01-09 12:04:48 +03:00
bol-van
0f42ff1731 ipset: mdig eagain support 2026-01-09 12:00:56 +03:00
bol-van
801328dc02 mdig: --eagain, --eagain-delay 2026-01-09 11:42:33 +03:00
bol-van
fdb9c9be60 mdig: increase EAGAIN attempts 2026-01-09 10:17:13 +03:00
bol-van
5e89db0c7b replace spaces with tabs 2026-01-08 20:43:55 +03:00
bol-van
0e95de6083 replace spaces with tabs 2026-01-08 20:43:20 +03:00
bol-van
3ec585c97e init.d: 99-lan-filter custom script 2026-01-08 20:20:52 +03:00
bol-van
577959f442 init.d: nft_detele_chain => nft_del_chain 2026-01-08 19:14:47 +03:00
bol-van
36731cd9b5 zapret1 unfixed parts 2026-01-08 19:13:34 +03:00
bol-van
b3b8133c39 nfqws2: minor safety fix 2026-01-08 12:19:41 +03:00
bol-van
5f96ce1099 nfqws2: minor safety fix 2026-01-08 12:18:54 +03:00
bol-van
2088f593d4 nfqws2: remove unused code 2026-01-08 11:55:51 +03:00
bol-van
03152ba76f nfqws2: move rawsend_cleanup 2026-01-08 11:46:45 +03:00
bol-van
f94d1b1d16 nfqws2: ignore trailing spaces and tabs in hostlists and ipsets 2026-01-08 11:38:13 +03:00
bol-van
790a2ca355 nfqws2: params leaks fix 2026-01-07 14:45:09 +03:00
bol-van
f318397726 AI inspired fixes 2026-01-07 13:44:56 +03:00
bol-van
5a116cf9be nfqws2: memleak fix 2026-01-07 13:18:30 +03:00
bol-van
d40f05865b zapret-tests: improve resolve tests 2026-01-07 12:35:19 +03:00
bol-van
e47603281c zapret-tests: improve resolve tests 2026-01-07 12:27:27 +03:00
bol-van
8ba58c8f16 update docs 2026-01-07 08:32:44 +03:00
bol-van
2def9397a0 zapret-lib: add expected_ratio to z_readfile 2026-01-07 08:31:23 +03:00
bol-van
a61895778b update docs 2026-01-07 08:26:51 +03:00
bol-van
a622061b45 nfqws2: optimize realloc increment 2026-01-07 08:24:04 +03:00
bol-van
1bbd342ff2 update docs 2026-01-07 08:15:43 +03:00
bol-van
84f978cee4 update docs 2026-01-07 08:14:24 +03:00
bol-van
dd3cffca5f update docs 2026-01-07 08:13:02 +03:00
bol-van
b699e5d9ec nfqws2, zapret-lib: more gzip optimizations 2026-01-07 08:09:41 +03:00
bol-van
e6591575fe ipset: -9 gzip ratio 2026-01-07 07:03:12 +03:00
bol-van
ca7569f68a update docs 2026-01-07 06:52:51 +03:00
bol-van
3a16523399 update docs 2026-01-07 06:51:58 +03:00
bol-van
2fd172118c nfqws2: change default expected gzip ratio 2026-01-07 06:50:15 +03:00
bol-van
c43574d056 nfqws2: gzip optimize memory alloc 2026-01-07 06:45:27 +03:00
bol-van
22d4df73f6 update docs 2026-01-07 06:36:14 +03:00
bol-van
23d6cddb30 nfqws2: coroutine compat 2026-01-06 23:12:28 +03:00
bol-van
c3b5d5e9ed update docs 2026-01-06 22:17:53 +03:00
bol-van
20856321c3 update docs 2026-01-06 22:15:31 +03:00
bol-van
75f3c7eac3 nfqws2: free zlib stream in __gc 2026-01-06 22:14:53 +03:00
bol-van
129461dc45 zapret-tests: gzip test 2026-01-06 21:06:14 +03:00
bol-van
91a3badc67 AI inspired fixes 2026-01-06 20:35:42 +03:00
bol-van
ff15bcceae nfqws2: fix clang warning 2026-01-06 17:18:46 +03:00
bol-van
61b20f86a7 update docs 2026-01-06 17:07:16 +03:00
bol-van
2de8809ead zapret-lib: writefile 2026-01-06 17:07:08 +03:00
bol-van
c77e8f799f update docs 2026-01-06 16:49:46 +03:00
bol-van
4cdf498a14 update docs 2026-01-06 16:48:33 +03:00
bol-van
4bbfc3081d update docs 2026-01-06 16:47:25 +03:00
bol-van
1099cf013d update docs 2026-01-06 16:46:42 +03:00
bol-van
cb85f6e672 zapret-lib: fix error message 2026-01-06 16:42:00 +03:00
bol-van
823f4a6fb6 zapret-lib: fix error message 2026-01-06 16:41:35 +03:00
bol-van
05647e84ef zapret-lib: do not error on premature file end 2026-01-06 16:40:58 +03:00
bol-van
8bc74d0c4f nfqws2, zapret-lib: gzip 2026-01-06 16:23:18 +03:00
bol-van
0eb6cc9722 nfqws2: remove unused lua code 2026-01-06 12:08:35 +03:00
bol-van
13594401c6 init.d: 80-dns-intercept fix wrong comments 2026-01-05 10:43:35 +03:00
bol-van
2983c681d7 update docs 2026-01-04 14:28:02 +03:00
bol-van
68eefd9dd7 update docs 2026-01-04 14:21:14 +03:00
bol-van
73f6f7c522 update docs 2026-01-04 14:18:54 +03:00
bol-van
df83a29b98 update docs 2026-01-04 14:17:07 +03:00
bol-van
9881cc4da2 update docs 2026-01-04 13:00:37 +03:00
bol-van
44f8ad6747 update docs 2026-01-04 12:38:33 +03:00
bol-van
c651367d6a update docs 2026-01-04 12:35:08 +03:00
bol-van
90f88271c5 update docs 2026-01-04 12:34:07 +03:00
bol-van
9ba8d6cbdf update docs 2026-01-04 12:18:17 +03:00
bol-van
27efbb37d7 update docs 2026-01-04 12:16:57 +03:00
bol-van
d725bd8fd7 update docs 2026-01-04 12:13:58 +03:00
bol-van
0ef50d04dc update docs 2026-01-04 12:13:33 +03:00
bol-van
fdae4b1812 update docs 2026-01-04 12:08:36 +03:00
bol-van
d0644f6160 update docs 2026-01-04 12:06:01 +03:00
bol-van
b4f1765574 update docs 2026-01-04 12:04:58 +03:00
bol-van
8454d48fcd update docs 2026-01-04 12:01:30 +03:00
bol-van
70d7a77d06 update docs 2026-01-04 11:56:51 +03:00
bol-van
2a48f82feb update docs 2026-01-04 11:54:34 +03:00
bol-van
c5d997ce48 update docs 2026-01-04 11:52:55 +03:00
bol-van
c950edb380 update docs 2026-01-04 11:39:23 +03:00
bol-van
0d96b03f49 blockcheck2: additional NOTEST 2026-01-04 11:38:47 +03:00
bol-van
9772641813 init.d: 80-dns-intercept use mangle iptable 2026-01-03 20:19:28 +03:00
bol-van
7307a03ff7 init.d: 80-dns-intercept print_op 2026-01-03 20:16:49 +03:00
bol-van
b529198f24 80-dns-intercept: remove DISABLE_IPVx filters 2026-01-03 19:59:51 +03:00
bol-van
5f5cfb434c update docs 2026-01-03 19:48:42 +03:00
bol-van
2f1aa5734e winws2: --wf-filter-loopback 2026-01-03 19:44:29 +03:00
bol-van
062360f3f3 update docs 2026-01-03 19:24:12 +03:00
bol-van
7122808425 init.d: dns intercept scheme 2026-01-03 19:14:35 +03:00
bol-van
515921522e init.d: ressurect lanif 2026-01-03 17:50:11 +03:00
bol-van
c0ce825a95 update lame issue warning 2026-01-03 15:04:39 +03:00
bol-van
c4b23d21ce init.d: sysv functions fix wrong interface order 2026-01-03 14:55:39 +03:00
bol-van
0847d9f140 nfqws2: replace printf with write in sighup 2026-01-03 13:24:18 +03:00
bol-van
b239690e33 AI inspired fixes 2026-01-03 13:15:01 +03:00
bol-van
4f6510daf1 base.sh: detect hard links to busybox 2026-01-03 00:39:29 +03:00
bol-van
0cad2329a1 install_bin: fix and 2026-01-03 00:39:03 +03:00
bol-van
24d9eb1fe2 nfqws2: use query name in dns response extraction 2026-01-03 00:12:43 +03:00
bol-van
f98445d36b update docs 2026-01-02 22:45:02 +03:00
bol-van
7278bb1b87 nfqws2: fix non-working dns ipcache if --debug=0 2026-01-02 20:01:23 +03:00
bol-van
5b58997e3e update docs 2026-01-02 19:53:22 +03:00
bol-van
93a6487eb5 update docs 2026-01-02 19:39:31 +03:00
bol-van
fdca797671 nfqws2: cache dns response IP addresses if --ipcache-hostname enabled 2026-01-02 19:29:33 +03:00
bol-van
bb9e78e8fb nfqws2: optimize udp protocol detect code 2026-01-02 17:44:52 +03:00
bol-van
2a15a1a778 Merge pull request #61 from Pavel4e5/typos
Typos
2026-01-02 17:26:44 +03:00
Pavel4e5
bf89b415bb Merge branch 'bol-van:master' into typos 2026-01-02 18:42:40 +05:00
bol-van
735936efc5 zapret-tests: test_swap 2026-01-01 14:26:23 +03:00
bol-van
9d09d8adcc nfqws2: fix comment 2025-12-31 18:07:30 +03:00
bol-van
3874e16075 nfqws2: print luajit status at startup 2025-12-31 16:10:22 +03:00
bol-van
cbb05967ba update docs 2025-12-31 10:49:19 +03:00
bol-van
665bd5f318 zapret-lib: check NFQWS2_COMPAT_VER 2025-12-31 10:48:42 +03:00
bol-van
fa1d7c30c3 blockcheck2: --payload= 2025-12-31 10:42:54 +03:00
Pavel4e5
940f94162d update docs 2025-12-31 02:47:05 +05:00
Pavel4e5
60108bf378 zapret-antidpi: correct error message 2025-12-31 02:40:33 +05:00
bol-van
5a68245e32 update docs 2025-12-30 15:33:28 +03:00
bol-van
b2dbdd4dd7 update docs 2025-12-30 15:32:55 +03:00
bol-van
5bc65c3b91 update docs 2025-12-30 15:20:49 +03:00
bol-van
6bf7f2c7c0 nfqws2: use luaL_loadbuffer 2025-12-30 15:11:15 +03:00
bol-van
44a80abb3f nfqws2: use luaL_loadbuffer 2025-12-30 15:05:42 +03:00
bol-van
89f0f39b83 update docs 2025-12-30 13:27:07 +03:00
bol-van
ad6f1db149 blockcheck2: http_unixeol test 2025-12-30 13:26:51 +03:00
bol-van
9154fe1677 zapret-lib, zapret-antidpi: http_reconstruct_req, http_unixeol 2025-12-30 13:26:15 +03:00
bol-van
5e63a0f5c5 update docs 2025-12-30 11:24:08 +03:00
bol-van
0521053991 github actions: use pigz -11 instead of gzip 2025-12-30 11:10:10 +03:00
bol-van
7b7ed1ad60 update docs 2025-12-30 10:51:07 +03:00
bol-van
2915647c63 update docs 2025-12-30 10:50:19 +03:00
bol-van
958a4e918b update docs 2025-12-30 10:48:11 +03:00
bol-van
cb332dad74 update docs 2025-12-30 10:44:05 +03:00
bol-van
17e9e0a8e6 update docs 2025-12-29 20:40:50 +03:00
bol-van
78b348a193 nfqws2: bu48 crash fix 2025-12-29 19:25:28 +03:00
bol-van
8103a02689 nfqws2: fix wrong bitset on 32-bit platforms 2025-12-29 19:14:25 +03:00
bol-van
a2dedc45c0 update docs 2025-12-29 18:19:30 +03:00
bol-van
f0d3a63df9 update docs 2025-12-29 18:18:57 +03:00
bol-van
c6ca25a656 nfqws2: lua gzip notice in help text 2025-12-29 18:16:43 +03:00
bol-van
71b87f749d actions: gzip lua in embedded release 2025-12-29 18:13:49 +03:00
bol-van
3d756c9702 nfqws2: support gzipped lua 2025-12-29 18:10:41 +03:00
bol-van
13864fe5c5 zapret-antidpi,zapret-lib: separate tls_client_hello_mod function 2025-12-29 17:16:15 +03:00
bol-van
cc2601af2f blockcheck2: fix missing --blob 2025-12-29 16:49:52 +03:00
bol-van
07319a329e update docs 2025-12-29 14:57:28 +03:00
bol-van
52f5c2697b update docs 2025-12-29 14:54:53 +03:00
bol-van
6b0dde5643 update docs 2025-12-29 14:53:16 +03:00
bol-van
e42265e071 update docs 2025-12-29 14:51:03 +03:00
bol-van
939f7a9558 update docs 2025-12-29 14:49:47 +03:00
bol-van
b62ebd8fcb update docs 2025-12-29 14:46:50 +03:00
bol-van
521fafc05d update docs 2025-12-29 14:46:01 +03:00
bol-van
419d6769bd update docs 2025-12-29 14:42:36 +03:00
bol-van
dde3f59d32 update docs 2025-12-29 14:42:19 +03:00
bol-van
78e1fb85ac zapret-antidpi: use TLS_EXT_SERVER_NAME 2025-12-29 14:08:34 +03:00
bol-van
f73790b871 zapret-lib: tls comments 2025-12-29 13:45:33 +03:00
bol-van
33f3378094 zapret-antidpi: extend tls clone function 2025-12-29 13:19:12 +03:00
bol-van
af7a6f6c10 zapret-antidpi: fix sniext add case 2025-12-29 13:10:35 +03:00
bol-van
9cc348e5bd zapret-antidpi: extend tls clone function 2025-12-29 13:03:48 +03:00
bol-van
8628c34941 zapret-lib: fix reconstruct handshake without record layer 2025-12-29 12:08:11 +03:00
bol-van
eec9f3e87c zapret-lib: tls dissector/reconstructor 2025-12-29 11:59:52 +03:00
bol-van
e4a8f51775 nfqws2: do not treat quic handshake messages as initials 2025-12-28 18:04:41 +03:00
bol-van
fb962df188 nfqws2: detect incoming quic_initial (w/o decryption) 2025-12-28 17:12:18 +03:00
bol-van
173dcd47d1 nfqws2: detect incoming quic_initial (w/o decryption) 2025-12-28 17:09:25 +03:00
bol-van
3439dc4f21 zapret-tests: remove unneeded code 2025-12-28 16:39:11 +03:00
bol-van
6e04162a20 github actions: remove arm-old target - luajit fail reason revealed 2025-12-28 15:32:09 +03:00
bol-van
883a3d6233 update docs 2025-12-28 15:14:01 +03:00
bol-van
e8cde6b0a2 rename sip.bin 2025-12-28 14:43:28 +03:00
bol-van
43872a21a6 more fakes 2025-12-28 13:45:10 +03:00
bol-van
ff2c3e81f9 update docs 2025-12-28 13:01:54 +03:00
bol-van
bcbfb45c53 update docs 2025-12-28 12:53:19 +03:00
bol-van
fa6a75f139 update docs 2025-12-28 12:51:10 +03:00
bol-van
e96c06598c update docs 2025-12-28 12:50:35 +03:00
bol-van
58320aecbe nfqws2: swap24 2025-12-28 12:49:09 +03:00
bol-van
ba526b75e1 update docs 2025-12-28 12:40:00 +03:00
bol-van
b9321619fc update docs 2025-12-28 12:37:58 +03:00
bol-van
d1a489a196 nfqws2: support 48-bit arithmetics 2025-12-28 12:32:26 +03:00
bol-van
cf91697dfb update docs 2025-12-28 10:55:08 +03:00
bol-van
401886bf32 update docs 2025-12-28 10:51:38 +03:00
bol-van
8baf81a840 update docs 2025-12-28 10:51:18 +03:00
bol-van
417cd8335a update docs 2025-12-28 10:48:26 +03:00
bol-van
5a9d40ad3f update docs 2025-12-28 10:47:42 +03:00
bol-van
af0be0fd94 update docs 2025-12-28 10:46:59 +03:00
bol-van
68e0c367c9 blockcheck2: fix broken parts 2025-12-28 10:27:21 +03:00
bol-van
0969d22391 nfqws2: wrong type fix 2025-12-27 19:55:10 +03:00
bol-van
94daca8ced nfqws2: wrong type fix 2025-12-27 19:51:34 +03:00
bol-van
1982984a86 nfqws2: fix crash 2025-12-27 19:50:12 +03:00
bol-van
6a520f508a winws2: no EACCES check in windows 2025-12-27 11:52:10 +03:00
bol-van
70d0dd5d79 nfqws2: permissions info if EACCES on lua files 2025-12-27 10:44:27 +03:00
bol-van
4ca0f6b574 update docs 2025-12-26 16:19:45 +03:00
bol-van
76e85d8969 update docs 2025-12-26 16:18:08 +03:00
bol-van
f458a76880 update docs 2025-12-26 14:28:43 +03:00
bol-van
6077d363ec more fakes 2025-12-26 13:02:53 +03:00
bol-van
c70f114c3a zapret-antidpi: dht_dn 3 by default 2025-12-26 10:51:37 +03:00
bol-van
2c037dca73 init.d: 50-dht4all NFQWS_OPT_DHT_PKT_OUT 2025-12-26 10:50:20 +03:00
bol-van
fe2fc0337f update docs 2025-12-25 20:51:08 +03:00
bol-van
b3a86d0d8a update docs 2025-12-25 20:48:31 +03:00
bol-van
5618be9a71 update docs 2025-12-25 20:47:35 +03:00
bol-van
715ae4bf1c update docs 2025-12-25 20:16:10 +03:00
bol-van
f44b6bf769 update docs 2025-12-25 20:15:07 +03:00
bol-van
e75857c448 update docs 2025-12-25 20:13:34 +03:00
bol-van
bc008e2cf3 update docs 2025-12-25 19:53:23 +03:00
bol-van
752226208b update docs 2025-12-25 19:49:03 +03:00
bol-van
9e2222549e init.d: 50-wg4all catch also response and cookie 2025-12-25 16:38:09 +03:00
bol-van
b0686b16f7 update docs 2025-12-25 16:20:51 +03:00
bol-van
d5b2c41daa update docs 2025-12-25 16:19:07 +03:00
bol-van
46a7632f59 50-dht4all iptables fix 2025-12-25 16:13:42 +03:00
bol-van
0642969a2d 50-dht4all fix comment 2025-12-25 16:07:33 +03:00
bol-van
13af2ec1be chmod 2025-12-25 16:02:12 +03:00
bol-van
50a1bb72d9 change dht and wireguard detection 2025-12-25 15:54:49 +03:00
bol-van
1696f1b552 update docs 2025-12-25 12:06:39 +03:00
bol-van
b0ce5c0c1b nfqws2: harden tls handshake detection 2025-12-24 17:18:25 +03:00
bol-van
87943846d9 update docs 2025-12-24 16:43:45 +03:00
bol-van
8b359d0410 update docs 2025-12-24 16:39:03 +03:00
bol-van
0430d9d9cd zapret-pcap: move file:close 2025-12-24 16:16:34 +03:00
bol-van
efcc1477dd update docs 2025-12-24 14:27:43 +03:00
bol-van
100fff0461 update docs 2025-12-24 14:26:51 +03:00
bol-van
1d14f8b0a4 update docs 2025-12-24 12:58:09 +03:00
bol-van
6e5c6511d3 update docs 2025-12-24 12:57:02 +03:00
bol-van
491a24d671 update docs 2025-12-24 12:53:48 +03:00
bol-van
505e8ff82c zapret-auto: tcp options nil 2025-12-24 00:12:49 +03:00
bol-van
1bbc56dc1b zapret-auto: desync.track presence check 2025-12-24 00:10:32 +03:00
bol-van
ad60550bf3 update docs 2025-12-23 23:52:34 +03:00
bol-van
3043963e28 nfqws2,zapret-auto: ip6flow fixes 2025-12-23 23:48:32 +03:00
bol-van
664bc60175 winws2: send to interface 1.0 if no ifname given 2025-12-23 23:01:36 +03:00
bol-van
815801a7db zapret-auto: preserve interface name in rst send 2025-12-23 22:24:21 +03:00
bol-van
05f54086cf zapret-auto: add reset to detector defaults 2025-12-23 22:14:52 +03:00
bol-van
b7a5f0410f nfqws2: minor lua safety checks 2025-12-23 21:57:25 +03:00
bol-van
da8bb9f5b8 nfqws2: struct iphdr -> ip 2025-12-23 21:39:04 +03:00
bol-van
9e52d767d1 update docs 2025-12-23 15:31:31 +03:00
bol-van
3ff06303cb init.d: autohostlist reset feature 2025-12-23 15:30:31 +03:00
bol-van
2a5c036909 nfqws2,zapret-auto: reset retransmitter 2025-12-23 15:13:33 +03:00
bol-van
a6e11540ff zapret-auto: reset parameter to standard_detector 2025-12-23 10:27:23 +03:00
bol-van
347c35e588 update docs 2025-12-23 09:52:17 +03:00
bol-van
ea28460f1d update docs 2025-12-23 09:49:47 +03:00
bol-van
0ac5df9d0e update docs 2025-12-22 20:54:44 +03:00
bol-van
63767929a0 nfqws2: dtls, reevaulate profile on l7/host discovery in any direction 2025-12-22 17:42:53 +03:00
bol-van
026c832f3f update docs 2025-12-22 13:55:54 +03:00
bol-van
53ef85773e update docs 2025-12-22 13:53:54 +03:00
bol-van
c41353cb8a update docs 2025-12-22 13:53:00 +03:00
bol-van
d2f6c18adf update docs 2025-12-22 13:52:45 +03:00
bol-van
00d1406791 update docs 2025-12-22 12:21:52 +03:00
bol-van
a38acae652 update docs 2025-12-22 12:16:28 +03:00
bol-van
90a991b5ee update docs 2025-12-22 12:14:47 +03:00
bol-van
686721f96a zapret-lib: wsize_rewrite change dlog text 2025-12-22 11:34:01 +03:00
bol-van
479b067f1a update docs 2025-12-21 23:28:46 +03:00
bol-van
ea1f34c833 update docs 2025-12-21 23:27:29 +03:00
bol-van
b4fe028cb7 update docs 2025-12-21 23:26:18 +03:00
bol-van
39c3640477 update docs 2025-12-21 23:18:49 +03:00
bol-van
2236a95d49 update docs 2025-12-21 23:08:18 +03:00
bol-van
8bb03d68b5 update docs 2025-12-21 23:05:34 +03:00
bol-van
7b2a9a26ed update docs 2025-12-21 23:02:52 +03:00
bol-van
b0ae1ac6f8 update docs 2025-12-21 21:56:00 +03:00
bol-van
29c1d1f164 update docs 2025-12-21 21:52:42 +03:00
bol-van
7cedbc5630 update docs 2025-12-21 21:45:18 +03:00
bol-van
ccd943a02b update docs 2025-12-21 21:42:31 +03:00
bol-van
49dc116c4b update docs 2025-12-21 21:38:51 +03:00
bol-van
f70107fad3 update docs 2025-12-21 21:37:50 +03:00
bol-van
40e9edcdcb init.d: fix 20-fw-extra 2025-12-21 21:22:27 +03:00
bol-van
905677b7ac init.d: remove unneeded code 2025-12-21 20:58:53 +03:00
bol-van
87b7b644c7 update docs 2025-12-21 16:20:09 +03:00
bol-van
2b410318ff blockcheck2: optionally replace multidisorder with multidisorder_legacy 2025-12-21 16:18:32 +03:00
bol-van
afee286d91 update docs 2025-12-21 16:07:55 +03:00
bol-van
f223a3e7e9 update docs 2025-12-21 16:05:02 +03:00
bol-van
258e353a52 update docs 2025-12-21 16:03:14 +03:00
bol-van
934d6e3e91 update docs 2025-12-21 16:00:42 +03:00
bol-van
630fb94466 update docs 2025-12-21 15:57:56 +03:00
bol-van
87617d379b update config.default 2025-12-21 15:38:12 +03:00
bol-van
1b6b3306aa init.d: remove unused code 2025-12-21 15:33:22 +03:00
bol-van
2cf74b3ed6 nfqws2: fix 'reasm cancelled' if no incoming traffic redirected 2025-12-21 14:52:08 +03:00
bol-van
0cd6f97b68 update docs 2025-12-20 23:13:36 +03:00
bol-van
3e2ead29da update docs 2025-12-20 17:47:57 +03:00
bol-van
ebffdfad08 update docs 2025-12-20 17:45:53 +03:00
bol-van
205a3ca528 update docs 2025-12-20 17:44:21 +03:00
bol-van
a014984f65 update docs 2025-12-20 17:42:55 +03:00
bol-van
c62f49fa86 blockcheck2: move ttl limiters to def.in 2025-12-20 16:47:47 +03:00
bol-van
5bf3f4029d ipset: reestr reduce file size limit 2025-12-20 15:26:31 +03:00
bol-van
b475f11c7c update docs 2025-12-20 14:48:56 +03:00
bol-van
021913aba2 ipset: renew get_reestr 2025-12-20 14:47:46 +03:00
bol-van
154d7d9c60 ipset: remove *reestr* because source does not and will probably not ever update 2025-12-20 14:07:42 +03:00
bol-van
7d6ddd557d zapret-antidpi: multidisorder_legacy change messages 2025-12-20 13:25:22 +03:00
bol-van
600345b3ec update docs 2025-12-20 13:19:09 +03:00
bol-van
7923535849 zapret-antidpi: multidisorder_legacy VERDICT_DROP 2025-12-20 13:10:11 +03:00
bol-van
e8d8e3f7d2 zapret-antidpi: multidisorder_legacy 2025-12-20 13:04:07 +03:00
bol-van
c6e6b51077 update docs 2025-12-20 11:00:12 +03:00
bol-van
c1acca07c3 update docs 2025-12-20 10:52:04 +03:00
bol-van
4cc52b9d24 zapret-auto: iff/neg in repeater 2025-12-20 10:48:01 +03:00
bol-van
0c4ef51b2a blockcheck2: change multi cut point from 1360 to 1220 2025-12-20 10:18:53 +03:00
bol-van
1027cb666d blockcheck2: 1,midsld,1360 pos for multi 2025-12-19 20:45:31 +03:00
bol-van
1920bbf862 update docs 2025-12-19 20:35:37 +03:00
bol-van
1a80e0cc0c update docs 2025-12-19 19:12:09 +03:00
bol-van
ebcd07b865 update docs 2025-12-19 19:10:50 +03:00
bol-van
eaecce9630 update docs 2025-12-19 19:10:14 +03:00
bol-van
17b7eb7c4b update docs 2025-12-19 19:09:00 +03:00
bol-van
12838003f8 update docs 2025-12-19 18:59:03 +03:00
bol-van
fa820b3e98 update docs 2025-12-19 18:57:13 +03:00
bol-van
af867002f4 update docs 2025-12-19 18:55:30 +03:00
bol-van
c6bc68d414 update docs 2025-12-19 18:55:03 +03:00
bol-van
801cacef58 update docs 2025-12-19 18:54:32 +03:00
bol-van
0df18df3f1 update docs 2025-12-19 18:53:39 +03:00
bol-van
4d9108822c update docs 2025-12-19 18:52:02 +03:00
bol-van
72f0b61cc0 actions: separate target arm-old with LUA 5.4 2025-12-19 18:01:00 +03:00
bol-van
99ea6e6fe0 actions: separate target arm-old with LUA 5.4 2025-12-19 17:47:56 +03:00
bol-van
99482d06d4 update docs 2025-12-19 13:56:55 +03:00
bol-van
65faaffe78 update docs 2025-12-19 13:55:19 +03:00
bol-van
81b2aa9d02 update docs 2025-12-19 13:52:39 +03:00
bol-van
e07239e717 update docs 2025-12-19 13:49:54 +03:00
bol-van
a5ca736ad7 update docs 2025-12-19 13:11:42 +03:00
bol-van
320f938418 update docs 2025-12-19 12:40:16 +03:00
bol-van
5e53ecfacb update docs 2025-12-19 12:33:20 +03:00
bol-van
d46edfdd55 update docs 2025-12-19 12:30:58 +03:00
bol-van
ec6e438144 blockcheck2: check quic only hopbyhop/destopt 2025-12-19 12:29:39 +03:00
bol-van
5b06f0b2a7 blockcheck2: check quic only hopbyhop/destopt 2025-12-19 11:52:11 +03:00
bol-van
ec1f5b5eff blockcheck2: check http3 with ipv6 exthdr 2025-12-19 11:47:55 +03:00
bol-van
774d9b79c0 dns fake 2025-12-19 11:41:55 +03:00
bol-van
176ccb6b8a update docs 2025-12-19 11:28:08 +03:00
bol-van
f0e31c0fd1 update docs 2025-12-19 11:27:21 +03:00
bol-van
7c3f1080e0 update docs 2025-12-19 10:46:42 +03:00
bol-van
3f760c778b update docs 2025-12-19 10:45:03 +03:00
bol-van
1b6b4c6b42 update docs 2025-12-18 17:28:51 +03:00
bol-van
6361a3798a update docs 2025-12-18 17:26:51 +03:00
bol-van
83feefdc18 update docs 2025-12-18 16:42:09 +03:00
bol-van
6d249528e4 zapret-antidpi: fix messages 2025-12-18 15:59:10 +03:00
bol-van
cf8874c4f5 zapret-lib: fix comment 2025-12-18 12:29:40 +03:00
bol-van
82955888b8 zapret-lib: repeater clear parameter 2025-12-18 12:20:28 +03:00
bol-van
eec1461867 zapret-lib: repeater support nested loops 2025-12-18 11:51:55 +03:00
bol-van
5e5dd241d4 zapret-auto: repeater - stop parameter 2025-12-18 11:17:50 +03:00
bol-van
8f53a44f7e zapret-lib: orchestrator 'repeater' 2025-12-17 22:54:22 +03:00
bol-van
03fd5acc95 update docs 2025-12-17 22:19:03 +03:00
bol-van
b40f5511d1 nfqws2: fix missing fclose 2025-12-17 21:55:10 +03:00
bol-van
89a662ed0a update docs 2025-12-17 21:28:13 +03:00
bol-van
c79822e5ef update docs 2025-12-17 20:54:01 +03:00
bol-van
3fd50eefb7 update docs 2025-12-17 20:51:27 +03:00
bol-van
2cdc45703a update docs 2025-12-17 20:50:36 +03:00
bol-van
5c77e78ad9 update docs 2025-12-17 20:49:54 +03:00
bol-van
48d59b436c update docs 2025-12-17 20:34:45 +03:00
bol-van
d829464843 update docs 2025-12-17 20:31:48 +03:00
bol-van
0fb44db47c update docs 2025-12-17 20:28:11 +03:00
bol-van
77cd246540 update docs 2025-12-17 20:25:03 +03:00
bol-van
b4d0ea465b update docs 2025-12-17 20:16:53 +03:00
bol-van
89cbed43dc update docs 2025-12-17 18:40:47 +03:00
bol-van
27ba59fa7f update docs 2025-12-17 18:36:45 +03:00
bol-van
df30a86305 update docs 2025-12-17 18:10:31 +03:00
bol-van
02349dcb1d update docs 2025-12-17 16:45:54 +03:00
bol-van
7bcca64f08 update docs 2025-12-17 16:44:09 +03:00
bol-van
14bf1ce69b update docs 2025-12-17 16:42:37 +03:00
bol-van
0034e75321 update docs 2025-12-17 15:51:57 +03:00
bol-van
f6c9f8b151 update docs 2025-12-17 15:51:05 +03:00
bol-van
76acf483f9 update docs 2025-12-17 15:45:08 +03:00
bol-van
e7e175dd82 nfqws2: fix parentheses 2025-12-17 14:38:03 +03:00
bol-van
68ac46d1d2 winws2: remove old comment 2025-12-17 14:27:51 +03:00
bol-van
2ecd34cbca winws2: harden sandbox 2025-12-17 13:43:13 +03:00
bol-van
b5b1f71fcc update docs 2025-12-17 11:05:09 +03:00
bol-van
f5f7de4086 nfqws2: fix broken l7proto profile rediscovery 2025-12-17 10:48:33 +03:00
bol-van
a331d59d33 update docs 2025-12-16 21:47:25 +03:00
bol-van
0a6d066e92 update docs 2025-12-16 19:39:01 +03:00
bol-van
1216ef0364 update docs 2025-12-16 19:35:07 +03:00
bol-van
52e38ee687 update docs 2025-12-16 19:31:51 +03:00
bol-van
fd53a54cf3 update docs 2025-12-16 19:31:22 +03:00
bol-van
c6b7e1fc43 update docs 2025-12-16 19:28:45 +03:00
bol-van
a7a1520b40 update docs 2025-12-16 19:27:09 +03:00
bol-van
04881b10b1 update docs 2025-12-16 18:17:02 +03:00
bol-van
561e5e2718 update docs 2025-12-16 18:15:55 +03:00
bol-van
e83e127c15 update docs 2025-12-16 18:10:08 +03:00
bol-van
3590861ffe update docs 2025-12-16 18:09:09 +03:00
bol-van
a12307d7f9 update docs 2025-12-16 18:07:00 +03:00
bol-van
25a9f9e426 update docs 2025-12-16 17:44:48 +03:00
bol-van
f4644e2a47 zapret-lib: update comment 2025-12-16 17:11:22 +03:00
bol-van
b9a0d42815 nfqws2: improve ctx magic protection 2025-12-16 16:00:29 +03:00
bol-van
f76beba434 nfqws2: fix instance_cutoff regression 2025-12-16 15:08:09 +03:00
bol-van
60b6ec2f49 nfqws2: lightuserdata safety check 2025-12-16 15:03:43 +03:00
bol-van
ce95210d1c update docs 2025-12-16 13:04:05 +03:00
bol-van
953d92b177 update docs 2025-12-16 13:00:23 +03:00
bol-van
4d9b4c9ad8 update docs 2025-12-16 12:59:35 +03:00
bol-van
ee7b72dc66 update docs 2025-12-16 12:57:54 +03:00
bol-van
8eb588d6a4 update docs 2025-12-16 12:46:36 +03:00
bol-van
08e1f8fba1 update docs 2025-12-15 21:22:15 +03:00
bol-van
454eedeb36 update docs 2025-12-15 21:20:09 +03:00
bol-van
7e761b3f03 update docs 2025-12-15 21:13:25 +03:00
bol-van
3dd51ee3b1 update docs 2025-12-15 21:12:48 +03:00
bol-van
07b1356c6c update docs 2025-12-15 21:11:23 +03:00
bol-van
23445785c9 update docs 2025-12-15 21:10:34 +03:00
bol-van
f4a7fe3aaf update docs 2025-12-15 19:27:16 +03:00
bol-van
6d31036ca1 update docs 2025-12-15 19:07:22 +03:00
bol-van
5ceb3aa301 update docs 2025-12-15 19:01:09 +03:00
bol-van
7fd602885f update docs 2025-12-15 18:59:43 +03:00
bol-van
af75c3d63d nfqws2: fix wrong comment 2025-12-15 18:49:51 +03:00
bol-van
cb9789668f nfqws2: fix wrong comment 2025-12-15 18:48:44 +03:00
bol-van
c16508e2e4 nfqws2: add l3_len, l4_len to dissect 2025-12-15 18:29:49 +03:00
bol-van
912eb1217a update docs 2025-12-15 17:12:27 +03:00
bol-van
3a328089a3 update docs 2025-12-15 17:05:31 +03:00
bol-van
4c76444b2d update docs 2025-12-15 17:04:46 +03:00
bol-van
403413bb26 update docs 2025-12-15 17:02:57 +03:00
bol-van
8ea6a17942 update docs 2025-12-15 17:00:17 +03:00
bol-van
15731d6135 update docs 2025-12-15 16:59:10 +03:00
bol-van
8255481787 update docs 2025-12-15 16:03:34 +03:00
bol-van
d2a919f71d update docs 2025-12-15 16:02:23 +03:00
bol-van
915130aed9 update docs 2025-12-15 15:55:28 +03:00
bol-van
901ffdfe5a update docs 2025-12-15 15:52:43 +03:00
bol-van
8caaf85b36 update docs 2025-12-15 14:46:03 +03:00
bol-van
1dc5e23a41 update docs 2025-12-15 14:44:06 +03:00
bol-van
ee859db268 update docs 2025-12-15 14:40:50 +03:00
bol-van
37f7fbbdec update docs 2025-12-15 14:40:08 +03:00
bol-van
81f6937187 update docs 2025-12-15 14:39:39 +03:00
bol-van
cbf5be50d1 update docs 2025-12-15 14:25:03 +03:00
bol-van
1966ea2298 nfqws2: define IPT_ECN_NOT_ECT 2025-12-15 14:20:40 +03:00
bol-van
d96350d2c7 nfqws2: define IPTOS_DSCP_MASK 2025-12-15 14:19:11 +03:00
bol-van
5cb96559d0 zapret-lib: seq compare functions 2025-12-15 11:31:51 +03:00
bol-van
dffba7cd13 rename seq_over_2G to rseq_over_2G 2025-12-15 11:11:04 +03:00
bol-van
5ad122da40 update docs 2025-12-15 11:04:47 +03:00
bol-van
54871f4ef8 nfqws2: regression 2025-12-15 11:01:23 +03:00
bol-van
d06e4f4c82 nfqws2,zapret-lib: check tcp seq overflow 2025-12-15 11:00:01 +03:00
bol-van
322b050e45 update docs 2025-12-14 21:55:46 +03:00
bol-van
5cb9cfc820 update docs 2025-12-14 21:55:26 +03:00
bol-van
ede260d4fa update docs 2025-12-14 21:54:19 +03:00
bol-van
9a7de03830 update docs 2025-12-14 21:43:02 +03:00
bol-van
b9b14f254a update docs 2025-12-14 21:41:28 +03:00
bol-van
653ed92cf8 update docs 2025-12-14 21:38:45 +03:00
bol-van
0d99c68b1b zapret-auto: do not nld if track.hostname_is_ip 2025-12-14 21:09:06 +03:00
bol-van
6c75dcc002 zapret-lua: circular change comments 2025-12-14 18:53:04 +03:00
bol-van
b76e1f65a3 zapret-auto: remove old comment 2025-12-14 18:41:08 +03:00
bol-van
de8845b89d zapret-auto: separate hostkey function 2025-12-14 18:14:42 +03:00
bol-van
f1eae764ab nfqws2: clean lua cutoff on profile change 2025-12-14 17:39:15 +03:00
bol-van
03c650b33c nfqws2: set fwmark to 0 in windows 2025-12-14 16:34:10 +03:00
bol-van
64b12c51e5 update docs 2025-12-14 16:28:43 +03:00
bol-van
2d8e031904 update docs 2025-12-14 16:26:56 +03:00
bol-van
28f0cd6e73 update docs 2025-12-14 16:19:24 +03:00
bol-van
9a9179a23b update docs 2025-12-14 16:18:36 +03:00
bol-van
48123bf1f7 update docs 2025-12-14 15:03:24 +03:00
bol-van
ece4e52676 update docs 2025-12-14 15:01:51 +03:00
bol-van
1d24d1e040 zapret-auto: update comment 2025-12-14 13:29:39 +03:00
bol-van
d0fd6b4868 update docs 2025-12-14 13:27:12 +03:00
bol-van
328408fa30 zapret-auto: deduplicate standard detector defaults 2025-12-14 13:20:28 +03:00
bol-van
0343bb248d zapret-auto: unify automate dlog prefix 2025-12-14 13:02:23 +03:00
bol-van
e4dd1574b8 zapret-auto: change function name 2025-12-14 13:00:39 +03:00
bol-van
1e3486ee14 zapret-auto: add success detector logic 2025-12-14 12:33:08 +03:00
bol-van
efe7470732 update docs 2025-12-13 23:48:26 +03:00
bol-van
8acd5690f4 update docs 2025-12-13 23:46:33 +03:00
bol-van
c2e3176a46 update docs 2025-12-13 23:44:27 +03:00
bol-van
658252d46a update docs 2025-12-13 23:43:06 +03:00
bol-van
5aaf7b3d6c update docs 2025-12-13 23:42:00 +03:00
bol-van
031ac7616d update docs 2025-12-13 23:41:16 +03:00
bol-van
098417d19f update docs 2025-12-13 23:40:43 +03:00
bol-van
2f0a74a11e update docs 2025-12-13 23:39:16 +03:00
bol-van
40c37c3448 update docs 2025-12-13 23:37:51 +03:00
bol-van
77fb530120 update docs 2025-12-13 23:36:52 +03:00
bol-van
faa0274521 update docs 2025-12-13 23:35:21 +03:00
bol-van
8a253d3d95 update docs 2025-12-13 23:34:36 +03:00
bol-van
0aac2965c1 nfqws2: minor reorder struct members 2025-12-13 22:13:04 +03:00
bol-van
d1128a8bc6 update docs 2025-12-13 20:56:17 +03:00
bol-van
e016fc0e42 update docs 2025-12-13 20:55:50 +03:00
bol-van
f48ea2f6a7 update docs 2025-12-13 20:39:03 +03:00
bol-van
2ab71ab895 update docs 2025-12-13 20:19:02 +03:00
bol-van
736e0ba3d4 update docs 2025-12-13 20:16:13 +03:00
bol-van
f2ae880c11 update docs 2025-12-13 20:15:05 +03:00
bol-van
019f3089c6 update docs 2025-12-13 20:09:12 +03:00
bol-van
30d28488c9 update docs 2025-12-13 19:53:54 +03:00
bol-van
5bcec4aada update docs 2025-12-13 19:50:16 +03:00
bol-van
886fbabcfc update docs 2025-12-13 17:00:17 +03:00
bol-van
cd8dbf2a2b update docs 2025-12-13 16:59:05 +03:00
bol-van
002742bd03 update docs 2025-12-13 16:56:45 +03:00
bol-van
dc2c707c3c update docs 2025-12-13 16:55:22 +03:00
bol-van
9630d0a9df update docs 2025-12-13 16:54:54 +03:00
bol-van
f4c4d5e558 update docs 2025-12-13 16:43:11 +03:00
bol-van
7b37880954 update docs 2025-12-13 16:39:53 +03:00
bol-van
6b7738ac16 update docs 2025-12-13 16:38:46 +03:00
bol-van
8dec014b50 update docs 2025-12-13 16:36:46 +03:00
bol-van
b0ee32f3dc update docs 2025-12-13 16:36:21 +03:00
bol-van
0e770ff46d update docs 2025-12-13 16:35:52 +03:00
bol-van
14b3aef030 update docs 2025-12-13 16:33:05 +03:00
bol-van
004c583595 update docs 2025-12-13 16:31:18 +03:00
bol-van
c4818a6a32 nfqws2: solved inability to get SSID using nl80211 on kernels 5.19+ 2025-12-13 15:33:57 +03:00
bol-van
58d57fed01 update docs 2025-12-13 11:27:16 +03:00
bol-van
d6b73fe7e0 update docs 2025-12-13 11:26:58 +03:00
bol-van
4867838fce update docs 2025-12-13 11:24:35 +03:00
bol-van
4b2551509f update docs 2025-12-13 11:22:16 +03:00
bol-van
ed6acb36a1 nfqws2: update docs 2025-12-12 23:45:32 +03:00
bol-van
26b80e80b6 nfqws2: update docs 2025-12-12 23:43:47 +03:00
bol-van
79b776b5a9 nfqws2: update docs 2025-12-12 23:42:27 +03:00
bol-van
3b251b9ee6 nfqws2: update docs 2025-12-12 23:41:43 +03:00
bol-van
8c65a966d9 nfqws2: update docs 2025-12-12 23:40:58 +03:00
bol-van
9da0b13aa3 nfqws2: update docs 2025-12-12 23:39:18 +03:00
bol-van
d7fd491121 nfqws2: update docs 2025-12-12 23:38:09 +03:00
bol-van
c60ef399ec nfqws2: update docs 2025-12-12 23:36:15 +03:00
bol-van
2abab21e4b nfqws2: update docs 2025-12-12 23:31:17 +03:00
bol-van
6190babb99 nfqws2: update docs 2025-12-12 23:29:55 +03:00
bol-van
7ce0b4a996 nfqws2: reduce default retrans maxseq to 32768, adjust config 2025-12-12 23:28:49 +03:00
bol-van
053556fe2d nfqws2: autohostlist reset fail counter if udp_in > threshold 2025-12-12 23:11:11 +03:00
bol-van
52571045fe nfqws2: add EOL at the end of truncated buffered DLOG line if it's too large. increase log line buffer 2025-12-12 20:37:58 +03:00
bol-van
db875ed1d4 nfqws2: cancel reasm if server window size is smaller than expected reasm size 2025-12-12 20:20:12 +03:00
bol-van
e828864811 nfqws2: cancel reasm if server window size is smaller than expected reasm size 2025-12-12 20:18:55 +03:00
bol-van
4404127fa3 update docs 2025-12-12 18:26:30 +03:00
bol-van
13e81e4b6f update docs 2025-12-12 18:25:45 +03:00
bol-van
a631add2d9 update docs 2025-12-12 18:24:34 +03:00
bol-van
26b9b63a20 update docs 2025-12-12 18:21:35 +03:00
bol-van
90489fad2f update docs 2025-12-12 18:21:17 +03:00
bol-van
d93c243d21 update docs 2025-12-12 18:20:46 +03:00
bol-van
65235d71d7 update docs 2025-12-12 18:19:53 +03:00
bol-van
fc01e6715f update docs 2025-12-12 18:04:18 +03:00
bol-van
1a33d68998 update docs 2025-12-12 18:00:57 +03:00
bol-van
dfaa475d2a update docs 2025-12-12 17:50:42 +03:00
bol-van
743018423a update docs 2025-12-12 17:47:15 +03:00
bol-van
762023f201 update docs 2025-12-12 16:45:16 +03:00
bol-van
a296b93b7a update docs 2025-12-12 16:44:17 +03:00
bol-van
1c9b3aa1bc update docs 2025-12-12 16:40:02 +03:00
bol-van
565fa8e337 init.d: fix non-working incoming redirect 2025-12-12 16:09:31 +03:00
bol-van
9fcecd07d1 update docs 2025-12-12 12:19:04 +03:00
bol-van
652e271877 update docs 2025-12-12 12:06:55 +03:00
bol-van
fc7ed4f4a8 update docs 2025-12-12 12:04:57 +03:00
bol-van
e9e5bdc860 update docs 2025-12-12 12:04:31 +03:00
bol-van
a2b8300219 update docs 2025-12-12 12:03:45 +03:00
bol-van
dfdcfbdf51 update docs 2025-12-12 12:02:12 +03:00
bol-van
170ec372fb update docs 2025-12-12 12:00:53 +03:00
bol-van
3f073908a6 update docs 2025-12-12 11:59:17 +03:00
bol-van
7708021587 nfqws2: rewrite autohostlist udp failure detector logic 2025-12-11 15:19:31 +03:00
bol-van
912aadf6ca zapret-auto: override host autostate key 2025-12-11 13:41:04 +03:00
bol-van
420cc0c3ef nfqws2: fix crash 2025-12-11 13:38:10 +03:00
bol-van
6ce5829d06 zapret-auto: override host autostate key 2025-12-11 12:57:32 +03:00
bol-van
a6d43af931 nfqws2: autohostlist do not react to rseq 0 2025-12-11 01:03:25 +03:00
bol-van
ca9898959e nfqws2: remove commented test code 2025-12-11 00:23:20 +03:00
bol-van
8cd2904614 nfqws2: push desync.track.pos.dt as float with nsec accuracy 2025-12-11 00:21:22 +03:00
bol-van
0de1ab1b1b init.d: AUTOHOSTLIST_INCOMING_MAXSEQ 2025-12-10 23:21:30 +03:00
bol-van
d1690aadcf nfqws2: autohostlist incoming failure triggers change 2025-12-10 23:11:28 +03:00
bol-van
2dd8533fb5 nfqws2,zapret-lib.lua,zapret-auto.lua: restructure conntrack record 2025-12-10 19:36:31 +03:00
bol-van
33ac18ea6b zapret-lib,zapret-auto: do not use desync copy to not lose VERDICT_MODIFY changes 2025-12-10 13:43:39 +03:00
bol-van
5c05c10f83 zapret-lib: return 0 if #val refers to non-string and non-table type 2025-12-10 10:49:46 +03:00
bol-van
7de0995d4a nfqws2,zapret-lib: fix non-working # and % arg subst under orchestrator 2025-12-10 10:28:48 +03:00
bol-van
a1c64e4dea update doc 2025-12-09 18:08:36 +03:00
bol-van
92b66b1535 update doc 2025-12-09 18:08:01 +03:00
bol-van
9bf4fb11e7 update doc 2025-12-09 18:05:08 +03:00
bol-van
7deeb04207 start writing manual.md 2025-12-09 18:00:24 +03:00
bol-van
776155a326 blockcheck2: fix unterminated string 2025-12-09 14:17:07 +03:00
bol-van
30423596ca zapret-lib: detect_payload_str 2025-12-09 12:18:59 +03:00
bol-van
27ef67adf9 zapret-auto: cond_payload_str 2025-12-09 11:48:23 +03:00
bol-van
bb604f111c zapret-auto: add comments 2025-12-09 11:22:09 +03:00
bol-van
e5174bc9ad zapret-auto: condition and stopif orchestrators 2025-12-09 10:50:54 +03:00
bol-van
6c29bf6702 zapret-lib,zapret-auto: allow nested orchestration 2025-12-09 09:52:24 +03:00
bol-van
976033be37 nfqws2: do not increase upseq_prev on empty packets 2025-12-09 09:52:08 +03:00
bol-van
f9b2135688 zapret-auto: add comments 2025-12-08 22:45:42 +03:00
bol-van
844fa6ab47 zapret-auto: optimize detector code 2025-12-08 20:02:26 +03:00
bol-van
dc0fe70bd6 zapret-auto: udp_in/udp_out failure detection 2025-12-08 19:46:00 +03:00
bol-van
2752c26795 blockcheck2: FOOLINGS_UDP overridable 2025-12-08 18:37:18 +03:00
bol-van
1600b41135 init.d: support --hostlist-auto-retrans-threshold 2025-12-08 16:52:49 +03:00
bol-van
2017889207 nfqws2: change retransmission detection scheme 2025-12-08 16:46:04 +03:00
bol-van
146ab847df nfqws2: allow dupsid with partial tls 2025-12-08 11:31:46 +03:00
bol-van
cf9059ed22 update changes.txt 2025-12-08 10:57:04 +03:00
bol-van
c94264c79e nfqws2: more fixes to reasm overlap support 2025-12-08 10:55:32 +03:00
bol-van
04cb71150a nfqws2: improve reasm overlap support 2025-12-08 10:35:26 +03:00
bol-van
378ee514c4 nfqws2: reasm support negative overlaps without gaps and without going beyond the starting seq 2025-12-08 09:55:44 +03:00
bol-van
1a190fcf9e nfqws2: increase tls_mod sni max size 2025-12-07 21:30:07 +03:00
bol-van
0f8a788351 zapret-auto: optimize code 2025-12-07 20:05:43 +03:00
bol-van
4c00f11c15 zapret-auto: move crec record get 2025-12-07 20:01:29 +03:00
bol-van
0f8cfd7022 zapret-lib: remove duplicate function 2025-12-07 19:59:31 +03:00
bol-van
4563b6ddcb blockcheck2: syndata tests 2025-12-07 19:44:28 +03:00
bol-van
9ae6927a0e zapret-auto: remove duplicate seq assignment 2025-12-07 17:03:45 +03:00
bol-van
8540278c9b zapret-antidpi: use tls_mod_shim 2025-12-07 17:00:55 +03:00
bol-van
76b9ab5075 zapret-lib: improve random seed 2025-12-07 16:52:37 +03:00
bol-van
3a153035e8 zapret-lib,zapret-antidpi: support sni=%var in tls_mod 2025-12-07 15:08:56 +03:00
bol-van
2b5eb3cd2d blockcheck2: remove newline print if test function absent 2025-12-07 14:31:56 +03:00
bol-van
2c35e8949a blockcheck2: fix brokern http3 test 2025-12-07 14:01:54 +03:00
bol-van
7edd428508 zapret-auto, zapret-lib: deduplicate plan instance execution code 2025-12-07 11:07:46 +03:00
bol-van
7749fce7dc zapret-auto: separate failure detection logic 2025-12-07 10:51:52 +03:00
bol-van
ea6e1e0853 blockcheck2: change qnum to allow parallel run with blockcheck1 for different domains 2025-12-07 09:46:32 +03:00
bol-van
7d2f12cbad zapret-auto: remove unused code 2025-12-06 23:50:35 +03:00
93 changed files with 15912 additions and 2639 deletions

View File

@@ -11,7 +11,11 @@ Issues - это место для обращений к разработчику
Discussions - место для обсуждения вопросов между пользователями.
Все, что выходит за рамки багов и технически грамотных предложений, идей,
вопросы типа "как мне это запустить", "что нажать", "что вписать" - будет безжалостно удаляться.
вопросы типа "как мне это запустить", "что нажать", "что вписать", "перестало открываться" - будет безжалостно удаляться.
Если вы не знаете как пользоваться, для вас что-то сложно, здесь - не место обучению программе или linux и не место для вопросов подобного рода.
Поймите, пожалуйста, что zapret - это инструмент, а не готовое решение для пользователя. В его функциях нет кнопки "открыть сайты", поэтому
если они перестали открываться - это не issue. Функцию "открыть сайты" дают только сборки - ищите их и все вопросы адресуйте туда.
Если вы игнорируете данное требование, вы не достигните своих целей , а только добавите желания удалить ваш issue или при настойчивости забанить.
Идите в дискуссии, не захламляйте issues.
Here is the place for bugs only. All questions, especially user-like questions (non-technical) go to Discussions.

View File

@@ -75,11 +75,11 @@ jobs:
sudo dpkg --add-architecture i386
sudo apt update -qq
if [[ "$ARCH" == lexra ]]; then
sudo apt install -y libcap-dev libc6:i386 zlib1g:i386
sudo apt install -y pigz libcap-dev libc6:i386 zlib1g:i386
URL=https://github.com/$REPO/raw/refs/heads/master/$DIR.txz
else
# luajit buildvm requires 32 bit executable on host platform for 32 bit cross targets
sudo apt install -y libcap-dev libc6-dev gcc-multilib
sudo apt install -y pigz libcap-dev libc6-dev gcc-multilib
URL=https://github.com/$REPO/releases/download/latest/$TOOL.tar.xz
fi
mkdir -p $HOME/tools
@@ -108,7 +108,7 @@ jobs:
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
export STAGING_DIR=$RUNNER_TEMP
if [[ "$ARCH" == lexra ]] || [[ "$ARCH" == ppc ]] || [[ "$ARCH" == x86 ]]; then
if [[ "$ARCH" == lexra ]] || [[ "$ARCH" == ppc ]] || [[ "$ARCH" == x86 ]] ; then
# use classic lua
wget -qO- https://www.lua.org/ftp/lua-${LUA_RELEASE}.tar.gz | tar -xz
(
@@ -553,6 +553,7 @@ jobs:
rm -rf binaries/{android*,freebsd*,win*} \
init.d/{openrc,pfsense,runit,s6,systemd,windivert.filter.examples} \
nfq2 ip2net mdig docs Makefile
pigz -11 lua/*.lua
)
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }}

View File

@@ -6,7 +6,7 @@ pktws_check_http()
[ "$NOTEST_BASIC_HTTP" = 1 ] && { echo "SKIPPED"; return; }
for s in 'http_hostcase' 'http_hostcase:spell=hoSt' 'http_domcase' 'http_methodeol'; do
pktws_curl_test_update $1 $2 --payload http_req --lua-desync=$s
for s in 'http_hostcase' 'http_hostcase:spell=hoSt' 'http_domcase' 'http_methodeol' 'http_unixeol'; do
pktws_curl_test_update $1 $2 --payload=http_req --lua-desync=$s
done
}

View File

@@ -5,7 +5,9 @@ pktws_check_http()
# $1 - test function
# $2 - domain
local PAYLOAD="--payload http_req" repeats ok
local PAYLOAD="--payload=http_req" repeats ok
[ "$NOTEST_MISC_HTTP" = 1 ] && { echo "SKIPPED"; return; }
for repeats in 1 20 100 260; do
# send starting bytes of original payload
@@ -20,7 +22,9 @@ pktws_check_https_tls12()
# $1 - test function
# $2 - domain
local PAYLOAD="--payload tls_client_hello" repeats ok
local PAYLOAD="--payload=tls_client_hello" repeats ok
[ "$NOTEST_MISC_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
for repeats in 1 20 100 260; do
# send starting bytes of original payload

View File

@@ -5,10 +5,10 @@ pktws_simple_split_tests()
# $3 - splits
# $4 - PRE args for nfqws2
local pos ok ok_any pre="$4"
local splitf splitfs="multisplit multidisorder"
local splitf splitfs="multisplit $MULTIDISORDER"
ok_any=0
for splitf in multisplit multidisorder; do
for splitf in $splitfs; do
eval need_$splitf=0
ok=0
for pos in $3; do
@@ -26,7 +26,7 @@ pktws_check_http()
# $1 - test function
# $2 - domain
local splits_http='method+2 midsld method+2,midsld'
local PAYLOAD="--payload http_req"
local PAYLOAD="--payload=http_req"
[ "$NOTEST_MULTI_HTTP" = 1 ] && { echo "SKIPPED"; return; }
@@ -38,8 +38,8 @@ pktws_check_https_tls()
# $1 - test function
# $2 - domain
# $3 - PRE args for nfqws2
local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
local PAYLOAD="--payload tls_client_hello"
local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,midsld,1220 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
local PAYLOAD="--payload=tls_client_hello"
[ "$NOTEST_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return; }

View File

@@ -5,7 +5,7 @@ pktws_check_http()
[ "$NOTEST_SEQOVL_HTTP" = 1 ] && { echo "SKIPPED"; return; }
local PAYLOAD="--payload http_req"
local PAYLOAD="--payload=http_req"
local ok pat= split f f2
@@ -24,8 +24,8 @@ pktws_check_http()
for split in 'method+1 method+2' 'midsld-1 midsld' 'method+1 method+2,midsld'; do
f="$(extract_arg 1 $split)"
f2="$(extract_arg 2 $split)"
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=multidisorder:pos=$f2:seqovl=$f
pktws_curl_test_update $1 $2 ${SEQOVL_PATTERN_HTTP:+--blob=$pat:@"$SEQOVL_PATTERN_HTTP" }$PAYLOAD --lua-desync=multidisorder:pos=$f2:seqovl=$f:seqovl_pattern=$pat
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f
pktws_curl_test_update $1 $2 ${SEQOVL_PATTERN_HTTP:+--blob=$pat:@"$SEQOVL_PATTERN_HTTP" }$PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f:seqovl_pattern=$pat
done
}
@@ -37,7 +37,7 @@ pktws_seqovl_tests_tls()
local ok ok_any
local testf=$1 domain="$2" pre="$3"
local pat rnd_mod padencap_mod split f f2
local PAYLOAD="--payload tls_client_hello"
local PAYLOAD="--payload=tls_client_hello"
pat=${SEQOVL_PATTERN_HTTPS:+seqovl_pat}
pat=${pat:-fake_default_tls}
@@ -47,21 +47,21 @@ pktws_seqovl_tests_tls()
ok=0
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=tcpseg:pos=0,-1:seqovl=1 --lua-desync=drop && ok=1
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$rnd_mod $pre $PAYLOAD --lua-desync=tcpseg:pos=0,-1:seqovl=#$pat:seqovl_pattern=$pat --lua-desync=drop && ok=1
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$pre $PAYLOAD $padencap_mod --lua-desync=tcpseg:pos=0,-1:seqovl=#pat:seqovl_pattern=pat --lua-desync=drop && ok=1
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$pre $PAYLOAD $padencap_mod --lua-desync=tcpseg:pos=0,-1:seqovl=#pat:seqovl_pattern=$pat --lua-desync=drop && ok=1
ok_any=$ok
ok=0
for split in 10 10,sniext+1 10,sniext+4 10,midsld; do
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=multisplit:pos=$split:seqovl=1 && ok=1
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$rnd_mod $pre $PAYLOAD --lua-desync=multisplit:pos=$split:seqovl=#$pat:seqovl_pattern=$pat && ok=1
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$pre $PAYLOAD $padencap_mod --lua-desync=multisplit:pos=$split:seqovl=#pat:seqovl_pattern=pat && ok=1
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$pre $PAYLOAD $padencap_mod --lua-desync=multisplit:pos=$split:seqovl=#pat:seqovl_pattern=$pat && ok=1
[ "$ok" = 1 -a "$SCANLEVEL" != force ] && break
done
for split in '1 2' 'sniext sniext+1' 'sniext+3 sniext+4' 'midsld-1 midsld' '1 2,midsld'; do
f="$(extract_arg 1 $split)"
f2="$(extract_arg 2 $split)"
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=multidisorder:pos=$f2:seqovl=$f && ok=1
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$rnd_mod $pre $PAYLOAD --lua-desync=multidisorder:pos=$f2:seqovl=$f:seqovl_pattern=$pat && ok=1
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f && ok=1
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$rnd_mod $pre $PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f:seqovl_pattern=$pat && ok=1
done
[ "$ok" = 1 ] && ok_any=1
[ "$ok_any" = 1 ]

View File

@@ -0,0 +1,53 @@
. "$TESTDIR/def.inc"
pktws_check_http()
{
# $1 - test function
# $2 - domain
local PAYLOAD="--payload=http_req" split
[ "$NOTEST_SYNDATA_HTTP" = 1 ] && { echo "SKIPPED"; return; }
for split in '' multisplit $MULTIDISORDER; do
pktws_curl_test_update "$1" "$2" --lua-desync=syndata ${split:+$PAYLOAD --lua-desync=$split}
pktws_curl_test_update "$1" "$2" --lua-desync=syndata:blob=fake_default_http $PAYLOAD ${split:+$PAYLOAD --lua-desync=$split}
done
}
pktws_check_https_tls()
{
# $1 - test function
# $2 - domain
# $3 - PRE args for nfqws2
local PAYLOAD="--payload=tls_client_hello" ok=0 pre="$3" split
[ "$NOTEST_SYNDATA_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
for split in '' multisplit $MULTIDISORDER; do
pktws_curl_test_update "$1" "$2" $pre --lua-desync=syndata ${split:+$PAYLOAD --lua-desync=$split} && ok=1
pktws_curl_test_update "$1" "$2" $pre --lua-desync=syndata:blob=0x1603 ${split:+$PAYLOAD --lua-desync=$split} && ok=1
pktws_curl_test_update "$1" "$2" $pre --lua-desync=syndata:blob=fake_default_tls:tls_mod=rnd,dupsid,rndsni ${split:+$PAYLOAD --lua-desync=$split} && ok=1
pktws_curl_test_update "$1" "$2" $pre --lua-desync=syndata:blob=fake_default_tls:tls_mod=rnd,dupsid,sni=google.com ${split:+$PAYLOAD --lua-desync=$split} && ok=1
done
[ "$ok" = 1 ]
}
pktws_check_https_tls12()
{
# $1 - test function
# $2 - domain
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
}
pktws_check_https_tls13()
{
# $1 - test function
# $2 - domain
pktws_check_https_tls "$1" "$2"
}

View File

@@ -40,7 +40,7 @@ pktws_check_http()
for ff in $fake 0x00000000; do
pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=fake_http:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS && ok=1
# duplicate SYN with MD5
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --payload empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --payload=empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
done
done
for ttl in $attls; do

View File

@@ -42,7 +42,7 @@ pktws_check_faked()
for split in $splits; do
pktws_curl_test_update $testf $domain ${FAKED_PATTERN:+--blob=faked_pat:@"$FAKED_PATTERN" }$pre $PAYLOAD --lua-desync=$splitf:${FAKED_PATTERN:+pattern=faked_pat:}pos=$split:$fooling && ok=1
# duplicate SYN with MD5
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKED_PATTERN:+--blob=faked_pat:@"$FAKED_PATTERN" }$pre $PAYLOAD --lua-desync=$splitf:${FAKED_PATTERN:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS --payload empty --out-range="<s1" --lua-desync=send:tcp_md5 && ok=1
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKED_PATTERN:+--blob=faked_pat:@"$FAKED_PATTERN" }$pre $PAYLOAD --lua-desync=$splitf:${FAKED_PATTERN:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS --payload=empty --out-range="<s1" --lua-desync=send:tcp_md5 && ok=1
done
done
for ttl in $attls; do

View File

@@ -22,7 +22,7 @@ pktws_check_http()
# do not test fake + multisplit if multisplit works
[ "$need_multisplit" = 0 -a "$SCANLEVEL" != force ] || splitfs=multisplit
# do not test fake + multidisorder if multidisorder works
[ "$need_multidisorder" = 0 -a "$SCANLEVEL" != force ] || splitfs="${splitfs:+$splitfs }multidisorder"
[ "$need_multidisorder" = 0 -a "$SCANLEVEL" != force ] || splitfs="${splitfs:+$splitfs }$MULTIDISORDER"
for splitf in $splitfs; do
ok=0
@@ -46,7 +46,7 @@ pktws_check_http()
for ff in $fake 0x00000000; do
pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split && ok=1
# duplicate SYN with MD5
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=fake_http:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split --payload empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=fake_http:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split --payload=empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
done
done
done
@@ -71,7 +71,7 @@ pktws_fake_https_vary_()
shift; shift; shift
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=multisplit:blob=$fake:$fooling:pos=2:nodrop:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid,padencap:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
[ "$ok_any" = 1 ] && ok=1
@@ -95,7 +95,7 @@ pktws_check_https_tls()
[ "$NOTEST_FAKE_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
local testf=$1 domain="$2" pre="$3"
local ok ok_any ttls attls f fake fooling splitf splitfs= split splits='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
local ok ok_any ttls attls f fake fooling splitf splitfs= split splits='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,midsld,1220 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
local PAYLOAD="--payload=tls_client_hello"
shift; shift
@@ -112,7 +112,7 @@ pktws_check_https_tls()
# do not test fake + multisplit if multisplit works
[ "$need_multisplit" = 0 -a "$SCANLEVEL" != force ] || splitfs=multisplit
# do not test fake + multidisorder if multidisorder works
[ "$need_multidisorder" = 0 -a "$SCANLEVEL" != force ] || splitfs="${splitfs:+$splitfs }multidisorder"
[ "$need_multidisorder" = 0 -a "$SCANLEVEL" != force ] || splitfs="${splitfs:+$splitfs }$MULTIDISORDER"
ok_any=0
for splitf in $splitfs; do

View File

@@ -46,7 +46,7 @@ pktws_check_http()
for ff in $fake 0x00000000; do
pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }${FAKED_PATTERN_HTTP:+--blob=faked_pat:@"$FAKED_PATTERN_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTP:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS && ok=1
# duplicate SYN with MD5
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }${FAKED_PATTERN_HTTP:+--blob=faked_pat:@"$FAKED_PATTERN_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTP:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS --payload empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }${FAKED_PATTERN_HTTP:+--blob=faked_pat:@"$FAKED_PATTERN_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTP:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS --payload=empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
done
done
done
@@ -71,7 +71,7 @@ pktws_fake_https_vary_()
shift; shift; shift
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
pktws_curl_test_update $testf $domain ${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
pktws_curl_test_update $testf $domain ${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=multisplit:blob=$fake:$fooling:pos=2:nodrop:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid,padencap:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
[ "$ok_any" = 1 ] && ok=1

View File

@@ -29,7 +29,7 @@ pktws_check_hostfake()
# $2 - domain
# $3 - PRE args for nfqws2
local testf=$1 domain="$2" pre="$3"
local ok ttls attls f fake fooling
local ok ttls attls f fooling
[ "$need_hostfakesplit" = 0 ] && return 0

View File

@@ -1,3 +1,5 @@
. "$TESTDIR/def.inc"
pktws_check_http3()
{
# $1 - test function
@@ -5,8 +7,8 @@ pktws_check_http3()
[ "$NOTEST_QUIC" = 1 ] && { echo "SKIPPED"; return; }
local repeats fake pos
local PAYLOAD="--payload quic_initial"
local repeats fake pos fool
local PAYLOAD="--payload=quic_initial"
if [ -n "$FAKE_QUIC" ]; then
fake=fake_quic
@@ -18,6 +20,12 @@ pktws_check_http3()
pktws_curl_test_update $1 $2 ${FAKE_QUIC:+--blob=$fake:@"$FAKE_QUIC" }$PAYLOAD --lua-desync=fake:blob=$fake:repeats=$repeats && [ "$SCANLEVEL" != force ] && break
done
[ "$IPV" = 6 ] && {
for fool in ip6_hopbyhop ip6_destopt ip6_hopbyhop:ip6_destopt; do
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=send:$fool --lua-desync=drop
done
}
for pos in 8 16 32 64; do
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=send:ipfrag:ipfrag_pos_udp=$pos --lua-desync=drop && [ "$SCANLEVEL" != force ] && break
done

View File

@@ -2,6 +2,16 @@ FOOLINGS46_TCP=${FOOLINGS46_TCP:-"tcp_md5 badsum tcp_seq=-3000 tcp_seq=1000000 t
FOOLINGS6_TCP=${FOOLINGS6_TCP:-"ip6_hopbyhop ip6_hopbyhop:ip6_hopbyhop2 ip6_destopt ip6_routing ip6_ah"}
FOOLINGS_TCP="$FOOLINGS46_TCP"
[ "$IPV" = 6 ] && FOOLINGS_TCP="$FOOLINGS_TCP $FOOLINGS6_TCP"
FOOLINGS_UDP="badsum"
FOOLINGS6_UDP="${FOOLINGS6_UDP:-$FOOLINGS6_TCP}"
FOOLINGS_UDP="${FOOLINGS_UDP:-badsum}"
[ "$IPV" = 6 ] && FOOLINGS_UDP="$FOOLINGS_UDP $FOOLINGS6_UDP"
FAKE_REPEATS=${FAKE_REPEATS:-1}
MIN_TTL=${MIN_TTL:-1}
MAX_TTL=${MAX_TTL:-12}
MIN_AUTOTTL_DELTA=${MIN_AUTOTTL_DELTA:-1}
MAX_AUTOTTL_DELTA=${MAX_AUTOTTL_DELTA:-5}
# can use MULTIDISORER=multidisorder_legacy
MULTIDISORDER=${MULTIDISORDER:-multidisorder}

View File

@@ -26,7 +26,7 @@ CURL=${CURL:-curl}
TEST_DEFAULT=${TEST_DEFAULT:-standard}
DOMAINS_DEFAULT=${DOMAINS_DEFAULT:-rutracker.org}
QNUM=${QNUM:-59780}
QNUM=${QNUM:-59781}
SOCKS_PORT=${SOCKS_PORT:-1993}
WS_UID=${WS_UID:-1}
WS_GID=${WS_GID:-3003}
@@ -40,10 +40,6 @@ IPFW_DIVERT_PORT=${IPFW_DIVERT_PORT:-59780}
CURL_MAX_TIME=${CURL_MAX_TIME:-2}
CURL_MAX_TIME_QUIC=${CURL_MAX_TIME_QUIC:-$CURL_MAX_TIME}
CURL_MAX_TIME_DOH=${CURL_MAX_TIME_DOH:-2}
MIN_TTL=${MIN_TTL:-1}
MAX_TTL=${MAX_TTL:-12}
MIN_AUTOTTL_DELTA=${MIN_AUTOTTL_DELTA:-1}
MAX_AUTOTTL_DELTA=${MAX_AUTOTTL_DELTA:-5}
USER_AGENT=${USER_AGENT:-Mozilla}
HTTP_PORT=${HTTP_PORT:-80}
HTTPS_PORT=${HTTPS_PORT:-443}
@@ -1199,8 +1195,8 @@ test_runner()
[ -f "$script" ] || continue
unset -f $FUNC
. "$script"
echo
existf $FUNC && {
echo
echo "* script : $TEST/$(basename "$script")"
$FUNC "$@"
}
@@ -1354,7 +1350,7 @@ check_domain_http_udp()
[ "$SKIP_PKTWS" = 1 ] || {
echo
echo preparing $PKTWSD redirection
mdig_resolve_all $IPV ips $4
mdig_resolve_all $IPV ips $3
pktws_ipt_prepare_udp $2 "$ips"
pktws_check_domain_http3_bypass $1 $3

View File

@@ -172,15 +172,23 @@ unique()
is_linked_to_busybox()
{
local IFS F P
local IFS F P BB
BB="$(which busybox)"
IFS=:
for path in $PATH; do
F=$path/$1
P="$(readlink $F)"
if [ -z "$P" ] && [ -x $F ] && [ ! -L $F ]; then return 1; fi
[ "${P%busybox*}" != "$P" ] && return
F="$path/$1"
if [ -L "$F" ]; then
P="$(readlink $F)"
if [ -z "$P" ] && [ -x $F ] && [ ! -L $F ]; then return 1; fi
[ "${P%busybox*}" != "$P" ] && return
elif [ -f "$F" -a -n "$BB" ]; then
# possible hardlink
[ $(get_dir_inode "$F") = $(get_dir_inode "$BB") ] && return
fi
done
return 1
}
get_dir_inode()
{
@@ -358,7 +366,7 @@ random()
local r rs
setup_random
if [ -c /dev/urandom ]; then
read rs </dev/urandom
rs=$(dd if=/dev/urandom count=1 bs=16 2>/dev/null | hexdump -e '1 "%02x"')
else
rs="$RANDOM$RANDOM$(date)"
fi

View File

@@ -37,8 +37,7 @@ ask_list()
local M_DEFAULT
eval M_DEFAULT="\$$1"
local M_ALL=$M_DEFAULT
local M=""
local m
local M="" m M_OLD
[ -n "$3" ] && { find_str_in_list "$M_DEFAULT" "$2" || M_DEFAULT="$3" ;}
@@ -54,5 +53,5 @@ ask_list()
echo selected : $M
eval $1="\"$M\""
[ "$M" != "$M_OLD" ]
[ "$M" != "$M_DEFAULT" ]
}

View File

@@ -522,11 +522,6 @@ install_openwrt_firewall()
{
echo \* installing firewall script $1
[ -n "MODE" ] || {
echo should specify MODE in $ZAPRET_CONFIG
exitp 7
}
echo "linking : $FW_SCRIPT_SRC => $OPENWRT_FW_INCLUDE"
ln -fs "$FW_SCRIPT_SRC" "$OPENWRT_FW_INCLUDE"

View File

@@ -2,8 +2,6 @@ std_ports
ipt_connbytes="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes"
IPSET_EXCLUDE="-m set ! --match-set nozapret"
IPSET_EXCLUDE6="-m set ! --match-set nozapret6"
IPBAN_EXCLUDE="-m set ! --match-set ipban"
IPBAN_EXCLUDE6="-m set ! --match-set ipban6"
ipt()
{
@@ -43,7 +41,7 @@ ipt6_add_del()
}
ipt6a_add_del()
{
on_off_function ipt6 ipt6a_del "$@"
on_off_function ipt6a ipt6_del "$@"
}
is_ipt_flow_offload_avail()

View File

@@ -25,7 +25,7 @@ filter_apply_hostlist_target()
{
# $1 - var name of nfqws params
local v parm parm1 parm2 parm3 parm4 parm5 parm6 parm7 parm8 parmNA
local v parm parm1 parm2 parm3 parm4 parm5 parm6 parm7 parm8 parm9 parm10 parm11 parm12 parm13 parmNA
eval v="\$$1"
if contains "$v" "$HOSTLIST_MARKER" || contains "$v" "$HOSTLIST_NOAUTO_MARKER"; then
[ "$MODE_FILTER" = hostlist -o "$MODE_FILTER" = autohostlist ] &&
@@ -40,10 +40,15 @@ filter_apply_hostlist_target()
parm5="${AUTOHOSTLIST_FAIL_THRESHOLD:+--hostlist-auto-fail-threshold=$AUTOHOSTLIST_FAIL_THRESHOLD}"
parm6="${AUTOHOSTLIST_FAIL_TIME:+--hostlist-auto-fail-time=$AUTOHOSTLIST_FAIL_TIME}"
parm7="${AUTOHOSTLIST_RETRANS_THRESHOLD:+--hostlist-auto-retrans-threshold=$AUTOHOSTLIST_RETRANS_THRESHOLD}"
parm8="--hostlist=$HOSTLIST_AUTO"
parm8="${AUTOHOSTLIST_RETRANS_RESET:+--hostlist-auto-retrans-reset=$AUTOHOSTLIST_RETRANS_RESET}"
parm9="${AUTOHOSTLIST_RETRANS_MAXSEQ:+--hostlist-auto-retrans-maxseq=$AUTOHOSTLIST_RETRANS_MAXSEQ}"
parm10="${AUTOHOSTLIST_INCOMING_MAXSEQ:+--hostlist-auto-incoming-maxseq=$AUTOHOSTLIST_INCOMING_MAXSEQ}"
parm11="${AUTOHOSTLIST_UDP_IN:+--hostlist-auto-udp-in=$AUTOHOSTLIST_UDP_IN}"
parm12="${AUTOHOSTLIST_UDP_OUT:+--hostlist-auto-udp-out=$AUTOHOSTLIST_UDP_OUT}"
parm13="--hostlist=$HOSTLIST_AUTO"
}
parm="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm4:+ $parm4}${parm5:+ $parm5}${parm6:+ $parm6}${parm7:+ $parm7}"
parmNA="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm8:+ $parm8}"
parm="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm4:+ $parm4}${parm5:+ $parm5}${parm6:+ $parm6}${parm7:+ $parm7}${parm8:+ $parm8}${parm9:+ $parm9}${parm10:+ $parm10}${parm11:+ $parm11}${parm12:+ $parm12}"
parmNA="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm13:+ $parm13}"
}
v="$(replace_str $HOSTLIST_NOAUTO_MARKER "$parmNA" "$v")"
v="$(replace_str $HOSTLIST_MARKER "$parm" "$v")"

View File

@@ -18,6 +18,18 @@ nft_list_table()
nft -t list table inet $ZAPRET_NFT_TABLE
}
nft_add_chain()
{
# $1 - chain
# $2 - params
nft add chain inet $ZAPRET_NFT_TABLE $1 "{ $2 }"
}
nft_del_chain()
{
# $1 - chain
nft delete chain inet $ZAPRET_NFT_TABLE $1
}
nft_create_set()
{
# $1 - set name
@@ -52,7 +64,7 @@ nft_flush_chain()
nft_chain_empty()
{
# $1 - chain name
local count=$(nft list chain inet $ZAPRET_NFT_TABLE prerouting | wc -l)
local count=$(nft list chain inet $ZAPRET_NFT_TABLE $1 | wc -l)
[ "$count" -le 4 ]
}
nft_rule_exists()
@@ -97,17 +109,19 @@ nft_activate_chain4()
{
# $1 - chain name
# $2 - saddr/daddr
local b rule markf= act
local b rule markf= act flt_ifname
[ "$DISABLE_IPV4" = "1" ] || {
eval act="\$${1}_act4"
[ -n "$act" ] && return
b=0
nft_wanif_filter_present && b=1
flt_ifname="oifname"
starts_with "$1" pre && flt_ifname="iifname"
[ "$2" = daddr ] && markf=$(nft_mark_filter)
rule="meta mark and $DESYNC_MARK == 0 $markf"
[ $b = 1 ] && rule="$rule oifname @wanif"
[ $b = 1 ] && rule="$rule $flt_ifname @wanif"
rule="$rule ip $2 != @nozapret jump $1"
nft_rule_exists ${1}_hook "$rule" || nft_add_rule ${1}_hook $rule
@@ -118,17 +132,19 @@ nft_activate_chain6()
{
# $1 - chain name
# $2 - saddr/daddr
local b rule markf=
local b rule markf= act flt_ifname
[ "$DISABLE_IPV6" = "1" ] || {
eval act="\$${1}_act6"
[ -n "$act" ] && return
b=0
nft_wanif6_filter_present && b=1
flt_ifname="oifname"
starts_with "$1" pre && flt_ifname="iifname"
[ "$2" = daddr ] && markf=$(nft_mark_filter)
rule="meta mark and $DESYNC_MARK == 0 $markf"
[ $b = 1 ] && rule="$rule oifname @wanif6"
[ $b = 1 ] && rule="$rule $flt_ifname @wanif6"
rule="$rule ip6 $2 != @nozapret6 jump $1"
nft_rule_exists ${1}_hook "$rule" || nft_add_rule ${1}_hook $rule
@@ -159,10 +175,10 @@ cat << EOF | nft -f -
add chain inet $ZAPRET_NFT_TABLE postnat_hook { type filter hook postrouting priority 101; }
flush chain inet $ZAPRET_NFT_TABLE postnat_hook
add chain inet $ZAPRET_NFT_TABLE prerouting_hook { type filter hook prerouting priority -99; }
flush chain inet $ZAPRET_NFT_TABLE prerouting_hook
add chain inet $ZAPRET_NFT_TABLE prerouting
flush chain inet $ZAPRET_NFT_TABLE prerouting
add chain inet $ZAPRET_NFT_TABLE prerouting_hook { type filter hook prerouting priority -99; }
flush chain inet $ZAPRET_NFT_TABLE prerouting_hook
add chain inet $ZAPRET_NFT_TABLE prenat_hook { type filter hook prerouting priority -101; }
flush chain inet $ZAPRET_NFT_TABLE prenat_hook
@@ -181,6 +197,7 @@ cat << EOF | nft -f -
add set inet $ZAPRET_NFT_TABLE wanif { type ifname; }
add set inet $ZAPRET_NFT_TABLE wanif6 { type ifname; }
add set inet $ZAPRET_NFT_TABLE lanif { type ifname; }
add chain inet $ZAPRET_NFT_TABLE ruletest
flush chain inet $ZAPRET_NFT_TABLE ruletest
@@ -226,8 +243,6 @@ cat << EOF | nft -f - 2>/dev/null
delete chain inet $ZAPRET_NFT_TABLE flow_offload_always
delete chain inet $ZAPRET_NFT_TABLE ruletest
EOF
# unfortunately this approach breaks udp desync of the connection initiating packet (new, first one)
# delete chain inet $ZAPRET_NFT_TABLE predefrag
}
nft_del_flowtable()
{
@@ -253,14 +268,17 @@ nft_create_or_update_flowtable()
nft_flush_ifsets()
{
cat << EOF | nft -f - 2>/dev/null
flush set inet $ZAPRET_NFT_TABLE wanif
flush set inet $ZAPRET_NFT_TABLE wanif6
for set in wanif wanif6 lanif; do
flush set inet $ZAPRET_NFT_TABLE $set
done
EOF
}
nft_list_ifsets()
{
nft list set inet $ZAPRET_NFT_TABLE wanif
nft list set inet $ZAPRET_NFT_TABLE wanif6
for set in wanif wanif6 lanif; do
nft list set inet $ZAPRET_NFT_TABLE $set
done
nft list flowtable inet $ZAPRET_NFT_TABLE ft 2>/dev/null
}
@@ -398,7 +416,9 @@ nft_fill_ifsets()
# calling all in one shot helps not to waste cpu time many times
script="flush set inet $ZAPRET_NFT_TABLE wanif
flush set inet $ZAPRET_NFT_TABLE wanif6"
flush set inet $ZAPRET_NFT_TABLE wanif6
flush set inet $ZAPRET_NFT_TABLE lanif"
nft_script_add_ifset_element lanif "$1"
[ "$DISABLE_IPV4" = "1" ] || nft_script_add_ifset_element wanif "$2"
[ "$DISABLE_IPV6" = "1" ] || nft_script_add_ifset_element wanif6 "$3"

View File

@@ -26,14 +26,25 @@ IPSET_OPT="hashsize 262144 maxelem $SET_MAXELEM"
IP2NET_OPT4="--prefix-length=22-30 --v4-threshold=3/4"
IP2NET_OPT6="--prefix-length=56-64 --v6-threshold=5"
# options for auto hostlist
# NOTE : in order for these adjustment to work it's required to redirect enough starting packets
# NOTE : set PKT_IN, PKT_OUT variables appropriately
AUTOHOSTLIST_INCOMING_MAXSEQ=4096
AUTOHOSTLIST_RETRANS_MAXSEQ=32768
AUTOHOSTLIST_RETRANS_RESET=1
AUTOHOSTLIST_RETRANS_THRESHOLD=3
AUTOHOSTLIST_FAIL_THRESHOLD=3
AUTOHOSTLIST_FAIL_TIME=60
AUTOHOSTLIST_UDP_IN=1
AUTOHOSTLIST_UDP_OUT=4
# 1 = debug autohostlist positives to ipset/zapret-hosts-auto-debug.log
AUTOHOSTLIST_DEBUGLOG=0
# number of parallel threads for domain list resolves
MDIG_THREADS=30
# EAI_AGAIN retries
MDIG_EAGAIN=10
# delay between EAI_AGAIN retries (ms)
MDIG_EAGAIN_DELAY=500
# ipset/*.sh can compress large lists
GZIP_LISTS=1
@@ -47,7 +58,7 @@ GZIP_LISTS=1
DESYNC_MARK=0x40000000
DESYNC_MARK_POSTNAT=0x20000000
# do not pass outgoing traffic to tpws/nfqws not marked with this bit
# do not pass outgoing traffic to 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
@@ -60,11 +71,10 @@ NFQWS2_PORTS_TCP=80,443
NFQWS2_PORTS_UDP=443
# PKT_OUT means connbytes dir original
# PKT_IN means connbytes dir reply
# this is --dpi-desync-cutoff=nX kernel mode implementation for linux. it saves a lot of CPU.
NFQWS2_TCP_PKT_OUT=$((6+$AUTOHOSTLIST_RETRANS_THRESHOLD))
NFQWS2_TCP_PKT_IN=3
NFQWS2_UDP_PKT_OUT=$((6+$AUTOHOSTLIST_RETRANS_THRESHOLD))
NFQWS2_UDP_PKT_IN=0
NFQWS2_TCP_PKT_OUT=20
NFQWS2_TCP_PKT_IN=10
NFQWS2_UDP_PKT_OUT=5
NFQWS2_UDP_PKT_IN=3
# redirect outgoing traffic without connbytes limiter and incoming with connbytes limiter
# normally it's needed only for stateless DPI that matches every packet in a single TCP session
# typical example are plain HTTP keep alives
@@ -92,11 +102,12 @@ FLOWOFFLOAD=donttouch
#OPENWRT_WAN4="wan vpn"
#OPENWRT_WAN6="wan6 vpn6"
# for routers based on desktop linux and macos. has no effect in openwrt.
# for routers based on classic linux. has no effect in openwrt.
# CHOOSE LAN and optinally WAN/WAN6 NETWORK INTERFACES
# or leave them commented if its not router
# it's possible to specify multiple interfaces like this : IFACE_WAN="eth0 eth1 eth2"
# if IFACE_WAN6 is not defined it take the value of IFACE_WAN
#IFACE_LAN=eth0
#IFACE_WAN=eth1
#IFACE_WAN6="ipsec0 wireguard0 he_net"

View File

@@ -61,3 +61,120 @@ v0.5
* zapret-lib: http_reply, url and nld dissectors
* zapret-lib: instance_cutoff_shim
* zapret-auto: circular orchestrator
v0.5.1
* zapret-auto: separate failure detection logic
* blockcheck2: fix broken http3 test
v0.6
* zapret-lib,zapret-antidpi: tls_mod_shim supports sni=%var subst
* blockcheck2: syndata tests
* nfqws2: reasm support negative overlaps. gaps are not supported.
* nfqws2,zapret-auto: changed retransmission detection scheme.
* zapret-auto: udp_in/udp_out failure detection
v0.6.1
* zapret-lib, zapret-auto: condition and stopif orchestrators
* zapret-lib: detect_payload_str - sample lua payload detector
* blockcheck2: unterminated string fix
v0.7
* nfqws2, zapret-lib : fix non-working % and # arg substitution under orchestrator
* nfqws2, zapret-lib : structure conntrack in/out positions. pass in desync.track.pos.{client,server,direct,reverse} position tables
* nfqws2: autohostlist: trigger RST and http redirect failures only within specified relative sequence
* nfqws2: autohostlist: trigger http redirect failure if payload is http_req without connection proto check
* nfqws2: push desync.track.pos.dt as float with nsec accuracy
* zapret-auto: override host autostate key in automate_host_record
* nfqws2: rewrite udp autohostlist failure detector logic
v0.7.1
* init.d: nft fix non-working incoming redirect
* nfqws2: cancel reasm if server window size is smaller than expected reasm size
* nfqws2: add EOL at the end of truncated buffered DLOG line if it's too large. increase log line buffer
* nfqws2: autohostlist reset fail counter if udp_in > threshold
* nfqws2: reduced default retrans maxseq to 32768
* nfqws2: solved inability to get SSID using nl80211 on kernels 5.19+
v0.7.2
* zapret-lib: fix broken is_retransmission()
* zapret-auto: add success detector logic
* nfqws2: clean lua cutoff on profile change
* zapret-auto: separate hostkey function
v0.7.4
* nfqws2, zapret-lib : check tcp sequence range overflow
* zapret-lib: seq compare functions
* nfqws2: add l3_len, l4_len to dissect
* nfqws2: fix broken l7proto profile rediscovery
* winws2: harden sandbox. disable child process execution , some UI interaction and desktop settings change
v0.7.5
* zapret-auto: orchestrator "repeater"
* blockcheck2: check http3 with ipv6 exthdr
* github actions: separate target arm-old with LUA classic, not JIT
* zapret-auto: iff/neg in repeater
* zapret-antidpi: multidisorder_legacy
* ipset: remove get_reestr_hostlist.sh and get_reestr_resolve.sh because zapret-info does not and will probably not ever update
* nfqws2: fix "reasm cancelled" if no incoming traffic redirected
* blockcheck2: MULTIDISORDER=multidisorder_legacy
v0.7.6
* nfqws2: reevaluate profile on l7/host discovery in any direction
* nfqws2: dtls protocol detection
* nfqws2: autohostlist reset retransmitter to break long wait
* zapret-auto: stadard_failure_detector reset retransmitter to break long wait
* nfqws2, init.d, windivert : dht and wg detection changes
v0.8.0
* init.d: 50-dht4all NFQWS_OPT_DHT_PKT_OUT
* nfqws2: (LUA_COMPAT_VER=4) support 48-bit arithmetics
* github actions: remove arm-old target - luajit fail reason revealed
* nfqws2: do not treat quic handshake messages as initials
* zapret-lib: tls dissector/reconstructor
* zapret-antidpi: tls_client_hello_clone
* zapret-antidpi: "optional" arg to blob taking functions
* nfqws2: support gzipped lua file. auto use script.lua.gz
v0.8.1
* nfqws2: fix bu48 crash and wrong results in bitset
* zapret-lib: http_reconstruct_req
* zapret-antidpi: http_unixeol
* blockcheck2: http_unixeol test
0.8.2
* nfqws2: do not start if NFQWS2_COMPAT_VER unexpected
* nfqws2: cache dns response IP addresses if --ipcache-hostname enabled
* winws2: remove hardcoded filter for loopback
* init.d: ressurect @lanif in nft scheme
* init.d: fix broken @wanif/@wanif6 fill in sysv nft scheme
* init.d: 80-dns-intercept
* winws2: --wf-filter-loopback
* blockcheck2: NOTEST_MISC_HTTP[S], NOTEST_SYNDATA_HTTP[S]
0.8.3
* nfqws2, zapret-lib: gzip compression and decompression
* nfqws2: ignore trailing spaces and tabs in hostlists and ipsets. "host.com " or "1.2.3.4 " are ok now
* init.d: 99-lan-filter custom script
* mdig: --eagain, --eagain-delay
0.8.4
* winws2: fix loopback large packets processing (up to 64K)
* zapret-lib, zapret-antidpi: use numeric indexes in http dissects
* nfqws2: move ctx from lightuserdata to userdata. prevents crashes on specific ARM cpus
* nfqws2: alternative representation of payload filter in execution_plan item
* nfqws2: --payload-disable
* nfqws2: gracefully shutdown on SIGINT and SIGTERM

View File

@@ -5,3 +5,7 @@ v2
* removed "stun_binding_req" specialized payload. replaced with common "stun" - any stun packets, not only binding request.
every LUA relying on desync.l7payload should be revised.
nfqws2 --payload option and init.d custom scripts must be updated.
v3
* restructured desync.track. pass positions in desync.track.pos.{client,server,direct,reverse}
code relying on conntrack counters and sequence numbers must be rewritten

5098
docs/manual.en.md Normal file

File diff suppressed because it is too large Load Diff

5302
docs/manual.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,6 @@
# zapret2 v0.2
## English
[Manual](manual.en.md)
## Зачем это нужно
@@ -10,6 +12,22 @@ VPN. Может использоваться для частичной проз
традиционные Linux-системы, FreeBSD, OpenBSD, Windows. В некоторых случаях возможна самостоятельная прикрутка
решения к различным прошивкам.
[Полный мануал](manual.md)
## Поддержать разработчика. Donations
Если вы считаете проект полезным и желаете поддержать разработку, направляйте ваши пожертвования на следующие адреса криптокошельков :
If you find this project useful and wish to donate here are crypto wallets :
USDT `0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E` (предпочительно сеть ERC-20. ERC-20 preferred)
BTC `bc1qhqew3mrvp47uk2vevt5sctp7p2x9m7m5kkchve`
ETH `0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E`
## Чем это отличается от zapret1
zapret2 является дальнейшим развитием проекта zapret.
@@ -24,12 +42,12 @@ zapret2 является дальнейшим развитием проекта
или хотя бы область , в которой их можно искать, плюс владеющий базовыми навыками программирования.
*nfqws2* оставляет в себе практически тот же функционал - распознавание протоколов, реассемблинг, дешифровка, управление профилями, хостлисты, ipset-ы, базовая фильтрация.
Но он полностью лишается возможностей самостоятельно воздействовать на трафик. Часть "дурения" переносится в скриптовой язык программирования LUA.
Но он полностью лишается возможностей самостоятельно воздействовать на трафик. Часть "дурения" переносится в скриптовой язык программирования Lua.
LUA код получает от C кода структурированное представление приходящих пакетов в виде дерева (диссекты), подобного тем, что вы видите в wireshark.
Lua код получает от C кода структурированное представление приходящих пакетов в виде дерева (диссекты), подобного тем, что вы видите в wireshark.
Туда же приходят результаты сборки или дешифровки частей некоторых протоколов (tls, quic).
С код предоставляет функции-хелперы, позволяющие отсылать пакеты, работать с двоичными данными, разбирать TLS, искать маркер-позции и т.д.
Имеется библиотека хелперов, написанных на LUA, а так же готовая библиотека программ атаки на DPI (стратегий), реализующая функции *nfqws1* в расширенном варианте
Имеется библиотека хелперов, написанных на Lua, а так же готовая библиотека программ атаки на DPI (стратегий), реализующая функции *nfqws1* в расширенном варианте
и с большей гибкостью.
Вы всегда сможете взять и дописать что-то свое. В этом и есть смысл, чтобы борьбой с DPI смог заняться любой, кто разбирается в пакетах.
@@ -40,8 +58,8 @@ zapret2 - инструмент для таких энтузиастов. Но э
## С чего начать
Хотелось бы избежать "талмуда" на главной странице. Поэтому начнем со способа запуска *nfqws2* и описания способов портирования стратегий *nfqws1* - как в *nfqws2* сделать то же самое, что можно было в *nfqws1*.
Когда вы поймете как это работает, вы можете посмотреть LUA код, находящийся "под капотом". Разобрать как он работает, попробовать написать что-то свое.
Хотелось бы избежать [талмуда](manual.md) на главной странице. Поэтому начнем со способа запуска *nfqws2* и описания способов портирования стратегий *nfqws1* - как в *nfqws2* сделать то же самое, что можно было в *nfqws1*.
Когда вы поймете как это работает, вы можете посмотреть Lua код, находящийся "под капотом". Разобрать как он работает, попробовать написать что-то свое.
"талмуд" обязательно будет, как он есть у любых более-менее сложных проектов. Он нужен как справочник.
### Механика обработки трафика
@@ -90,11 +108,11 @@ nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-antidpi.
--payload=tls_client_hello,http_req --lua-desync=multisplit:pos=1:seqovl=5:seqovl_pattern=0x1603030000
```
Данный пример предполагает, что в той же директории находятся файлы `zapret-lib.lua` - библиотека хелперов на LUA и `zapret-antidpi.lua` - библиотека базовых стратегий.
`--lua-init` может содержать LUA код в виде строки. Так удобно писать простой код, например присвоить константу переменной, чтобы не создавать файлы ради этой мелочи.
Данный пример предполагает, что в той же директории находятся файлы `zapret-lib.lua` - библиотека хелперов на Lua и `zapret-antidpi.lua` - библиотека базовых стратегий.
`--lua-init` может содержать Lua код в виде строки. Так удобно писать простой код, например присвоить константу переменной, чтобы не создавать файлы ради этой мелочи.
Либо подцепляется файл, если значение параметра начинается с `@`. Код из `--lua-init` выполняется 1 раз при старте.
Далее указаны параметры `--lua-desync`. Они содержат имя LUA функции, вызываемой при обработке каждого пакета, проходящего через профиль мультистратегии.
Далее указаны параметры `--lua-desync`. Они содержат имя Lua функции, вызываемой при обработке каждого пакета, проходящего через профиль мультистратегии.
После двоеточия и через двоеточия следуют параметры для данной функции в формате `param[=value]`. В примере реализована стратегия
```
@@ -110,7 +128,7 @@ nfqws --qnum 200 --debug \
Тип пейлоада - тип данных, содержащихся в пакете или группе пакетов. Например, протокол соединения может быть tls, а пейлоады - tls_client_hello, tls_server_hello, unknown.
Другое важное отличие - отсутствие жестко определенных фаз десинхронизации. То, что вы раньше писали как `fake,multisplit` реализуется двумя
последовательно вызываемыми LUA функциями. Их может быть столько, сколько нужно, учитывая логику прохождения пакетов и операций с ними, и у каждой могут быть свои параметры.
последовательно вызываемыми Lua функциями. Их может быть столько, сколько нужно, учитывая логику прохождения пакетов и операций с ними, и у каждой могут быть свои параметры.
Может даже несколько раз вызываться одна и так же функция с разными параметрами. Так, например, можно послать несколько фейков, причем с разными фулингами.
Конкретный вызов `--lua-desync` функции называется инстансом. Инстанс - это связка имени функции, номера вызова внутри профиля и номера самого профиля.
Это похоже на одну программу, которую можно запустить много раз с разными параметрами.
@@ -118,11 +136,11 @@ nfqws --qnum 200 --debug \
Другое немаловажное отличие - поддержка автоматической tcp сегментации средствами `zapret-lib.lua`. Вам больше не нужно думать о размерах отсылаемых tcp пакетов.
По каждому соединению отслеживается MSS. Если пакет не влезает в MSS, выполняется сегментация.
Например, это может случиться при отправке tls фейка с kyber. Или если вы режете kyber tls так, что одна из частей получается размером 1600 байт,
что, очевидно, не влезает в MTU. Или если вы задали seqovl=10000. В *nfqws1* такое значение вызвало бы ошибку. Функция LUA `rawsend_dissect_segmented` отправит
что, очевидно, не влезает в MTU. Или если вы задали seqovl=10000. В *nfqws1* такое значение вызвало бы ошибку. Функция Lua `rawsend_dissect_segmented` отправит
несколько tcp сегментов с начальным sequence -10000 общим размером 10000 байт, в последнем из которых будет кусок оригинального сообщения.
В *nfqws2* нет жестко зашитых параметров кастомных фейков типа `--dpi-desync-fake-tls`, `dpi-desync-fake-http` и тд.
Вместо них есть блобы. Блоб (blob) - это переменная LUA типа *string*, содержащая блок двоичных данных произвольной длины. От 1 байта до гигабайтов.
Вместо них есть блобы. Блоб (blob) - это переменная Lua типа *string*, содержащая блок двоичных данных произвольной длины. От 1 байта до гигабайтов.
*nfqws2* автоматически инициализирует блобы со стандартными фейками tls, http, quic, как это и было в *nfqws1*.
Блобы могут быть заданы как hex-строка прямо в параметре desync функции, либо пред-загружены при старте с помощью параметра `--blob=name:0xHEX|[+ofs]@filename`
@@ -155,15 +173,15 @@ range задается как `mX-mY`, `mX<mY`, `-mY`, `<mY`, `mX-`.
Следующий профиль снова принимает значения по умолчанию.
Что будет, если вы не напишите фильтр `--payload` для fake или multisplit ? В *nfqws1* без `--dpi-desync-any-protocol` они работали только по известным пейлоадам.
В *nfqws2* "any protocol" - режим по умолчанию. Однако, функции из библиотеки `zapret-antidpi.lua` написаны так, что по умолчанию работают только по известные пейлоадам
В *nfqws2* "any protocol" - режим по умолчанию. Однако, функции из библиотеки `zapret-antidpi.lua` написаны так, что по умолчанию работают только по известным пейлоадам
и не работают по пустым пакетам или unknown - точно так же, как это было в *nfqws1*.
Но лучше все-же писать фильтры `--payload`, потому что они работают на уровне C кода, который выполняется существенно быстрее, чем LUA.
Но лучше все-же писать фильтры `--payload`, потому что они работают на уровне C кода, который выполняется существенно быстрее, чем Lua.
Диссект пакета проходит поочередно по всем `--lua-desync` инстансам профиля, для которых не выполняется условие отсечения (cutoff).
Отсечение может быть по range, payload или добровольное отсечение. Последний вариант - когда инстанс сам отказывается обрабатывать пакеты
по входящему, исходящему или обоим направлениям. Например, задача стратегии wsize - отреагировать только на пакет с tcp флагами SYN,ACK. После этого он не нужен, в коде вызывается функция отсечения.
Это сделано для экономии ресурсов процессора.
Если все инстансы в профиле точно никогда больше не будут вызваны по соединению + направлению - вошли в превышение верхней границы range или выполнили добровольный cutoff, то движок LUA не вызывается вообще.
Если все инстансы в профиле точно никогда больше не будут вызваны по соединению + направлению - вошли в превышение верхней границы range или выполнили добровольный cutoff, то движок Lua не вызывается вообще.
От инстанса к инстансу содержимое диссекта может ими меняться. Следующий инстанс видит изменения предыдущего.
Каждый инстанс выносит свой вердикт - что делать с текущим диссектом. VERDICT_PASS - означает отправить как есть,
@@ -289,22 +307,21 @@ nfqws2 --lua-desync=send:ipfrag:ipfrag_pos_udp=8 --lua-desync=drop
Но это решаемо. А что не решаемо - это перехват вторых частей kyber tls hello. Их невозможно опознать без связи с предыдущими фрагментами. Поэтому перехватывается весь порт.
Для HTTP вопрос решаемый, поскольку там нет реассемблирования запросов, но http сейчас стал настолько редким, что и смысла нет заморачиваться.
Везде расставлены фильтры профиля мультистратегии `--filter-l7`, фильтры по `--out-range` и по `--payload`.
Зачем ? В основном для сокращения вызовов LUA кода, который заведомо медленнее C кода.
Если пакет не попадет в профили с LUA - ни о каком вызове кода LUA речи быть не может.
Если пакет попал в профиль с LUA, то после первых 10 пакетов с данными наступает отсечение по верхней границе range. Все LUA инстансы входят в состояние instance cutoff,
соединение входит в состояние "lua cutoff" по направлению "out". Значит вызовов LUA не будет вообще. Не просто вызовов, а даже обращения к движку LUA
с какой-либо целью. Будет только C код, который посмотрит на признак "cutoff" и сразу же отпустит пакет.
Везде расставлены фильтры профиля мультистратегии `--filter-l7`, фильтры по `--out-range` и по `--payload`. Зачем ? В основном для сокращения вызовов Lua кода, который заведомо медленнее C кода.
Если пакет не попадет в профили с Lua - ни о каком вызове кода Lua речи быть не может. Если пакет попал в профиль с Lua, то после первых 10 пакетов с данными наступает отсечение по верхней границе range. Все Lua инстансы входят в состояние instance cutoff, соединение входит в состояние "lua cutoff" по направлению "out". Значит вызовов Lua не будет вообще. Не просто вызовов, а даже обращения к движку Lua с какой-либо целью. Будет только C код, который посмотрит на признак "cutoff" и сразу же отпустит пакет.
Так же везде расставлены фильтры по payload type. Отчасти так же с целью сократить вызовы LUA даже в пределах первых 10 пакетов с данными.
Почему именно `-d10` ? Чтобы хватило для отработки большинства вариантов стратегий, учитывая возможные ретрансмиссии и плохую связь. В winws2 по умолчанию включен параметр `--wf-tcp-empty=0`. Он блокирует перехват пустых пакетов с ACK, что позволяет примерно в 2 раза сэкономить на процессоре при интенсивных скачиваниях. Пустые ACK в большинстве стратегий не нужны. Но это же и ломает счетчик "n" - он не будет показывать реальное количество пакетов по соединению. Счетчик "d" работать будет как надо.
Почему нет "-d10" на udp ? Потому что используется windivert фильтр на пейлоад. Счетчики будут считать не реальное количество пакетов в потоке, а количество перехваченных с отфильтрованными пейлоадами. Причем если интервал между ними будет более 1 минуты, то счет будет начинаться заново, поскольку таймаут udp по умолчанию - 60 сек. После таймаута запись conntrack будет удалена. Следующий пакет пойдет как новый поток.
Так же везде расставлены фильтры по payload type. Отчасти так же с целью сократить вызовы Lua даже в пределах первых 10 пакетов с данными.
С другой стороны, даже при совпадении протокола соединения (`--filter-l7`) может пробежать не интересующий нас пейлоад.
По умолчанию многие функции из `zapret-antidpi.lua` реагируют только на известные типы пейлоада, но не на конкретные, а на любые известные.
Если допустить малореальный, но гипотетически возможный сценарий, что в рамках протокола http будет отправлен блок данных с tls или фраза, похожая на сообщение из xmpp,
то тип пейлоада выскочит tls_client_hello или xmpp_stream, например. Лучше от этого сразу уберечься. Тем более что в других видах протоколов - xmpp, например, -
Если допустить малореальный, но гипотетически возможный сценарий, что в рамках протокола http будет отправлен блок данных с tls или фраза, похожая на сообщение из xmpp, то тип пейлоада выскочит tls_client_hello или xmpp_stream, например. Лучше от этого сразу уберечься. Тем более что в других видах протоколов - xmpp, например, -
пейлоады могут проскакивать нескольких типов вполне ожидаемо. Но работать надо не по всем.
В фейке для TLS по умолчанию - fake_default_tls - однократно при старте меняется SNI с "www.microsoft.com" на случайный и рандомизируется поле "random" в TLS handshake.
Это делается простой строчкой LUA кода. Больше нет никаких специальных параметров *nfqws2* для модификации пейлоадов.
Это делается простой строчкой Lua кода. Больше нет никаких специальных параметров *nfqws2* для модификации пейлоадов.
В профиле для youtube на лету меняется SNI на "www.google.com", копируется поле TLS "session id" с обрабатываемого в данный момент TLS handshake.
```
@@ -350,17 +367,14 @@ start "zapret: http,https,quic" /min "%~dp0winws2.exe" ^
--lua-desync=multidisorder:pos=midsld ^
--new ^
--filter-udp=443 --filter-l7=quic --hostlist="%~dp0files\list-youtube.txt" ^
--out-range=-d10 ^
--payload=quic_initial ^
--lua-desync=fake:blob=quic_google:repeats=11 ^
--new ^
--filter-udp=443 --filter-l7=quic ^
--out-range=-d10 ^
--payload=quic_initial ^
--lua-desync=fake:blob=fake_default_quic:repeats=11 ^
--new ^
--filter-l7=wireguard,stun,discord ^
--out-range=-d10 ^
--payload=wireguard_initiation,wireguard_cookie,stun,discord_ip_discovery ^
--lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2
```
@@ -372,9 +386,9 @@ start "zapret: http,https,quic" /min "%~dp0winws2.exe" ^
Надо послать исходный запрос с известным пейлоадом с seqovl случайного размера от 5 до 10 символов со случайным содержимым, состоящим из букв от a до z.
Здесь раскрывается не декларативный характер стратегий, а алгоритмический. Стратегия - это программа, и пишите ее вы на языке программирования.
Для облегчения простых или стандартных действий есть готовые средства, так что далеко не всегда надо писать свою функцию.
Частенько можно обойтись простенькими кусками LUA кода в дополнение к имеющимся.
Частенько можно обойтись простенькими кусками Lua кода в дополнение к имеющимся.
Здесь используется функция `luaexec`, предназначенная для динамического выполнения LUA кода в процессе обработки текущего диссекта.
Здесь используется функция `luaexec`, предназначенная для динамического выполнения Lua кода в процессе обработки текущего диссекта.
Она инициализирует требуемый blob, записывая его в таблицу desync, которая передается от инстанса к инстансу.
Следующий инстанс `tcpseg` использует `rnd` как blob - источник seqovl паттерна.
@@ -405,4 +419,4 @@ nfqws2 \
### Очень важный совет
Научитесь пользоваться `--debug` логом. Без него будет очень сложно понять *nfqws2* на начальном этапе и приспособиться к новой схеме.
Ошибок будет много. Особенно, когда вы начнете писать свой LUA код. Их надо читать.
Ошибок будет много. Особенно, когда вы начнете писать свой Lua код. Их надо читать.

BIN
files/fake/bgp_open.bin Normal file

Binary file not shown.

BIN
files/fake/bitcoin.bin Normal file

Binary file not shown.

BIN
files/fake/dns.bin Normal file

Binary file not shown.

Binary file not shown.

BIN
files/fake/ntp4.bin Normal file

Binary file not shown.

View File

@@ -0,0 +1,4 @@
OPTIONS rtsp://10.2.2.2:8554/ RTSP/1.0
CSeq: 2
User-Agent: LibVLC/3.0.16 (LIVE555 Streaming Media v2016.11.28)

1
files/fake/smtp_ehlo.bin Normal file
View File

@@ -0,0 +1 @@
EHLO delta.peach.mil

Binary file not shown.

BIN
files/fake/tls_alert.bin Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

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

View File

@@ -1,8 +1,10 @@
# this custom script runs desync to DHT packets with udp payload length 101..399 , without ipset/hostlist filtering
# this custom script runs desync to DHT packets with udp payload length >=5 , 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:---payload dht --lua-desync=dht_dn}"
# set it to "keepalive" to fool all packets, not just the first. or set number of packets to be fooled.
NFQWS_OPT_DHT_PKT_OUT=${NFQWS_OPT_DHT_PKT_OUT:-20}
alloc_dnum DNUM_DHT4ALL
alloc_qnum QNUM_DHT4ALL
@@ -19,11 +21,11 @@ zapret_custom_firewall()
# $1 - 1 - run, 0 - stop
local f uf4 uf6
local first_packet_only="$ipt_connbytes 1:1"
local first_packet_only=$(ipt_first_packets $NFQWS_OPT_DHT_PKT_OUT)
f='-p udp -m length --length 109:407 -m u32 --u32'
uf4='0>>22&0x3C@8>>16=0x6431'
uf6='48>>16=0x6431'
f='-p udp -m u32 --u32'
uf4='0>>22&0x3C@4>>16=13:0xFFFF&&0>>22&0x3C@8>>16=0x6431:0x6432'
uf6='44>>16=13:0xFFFF&&48>>16=0x6431:0x6432'
fw_nfqws_post $1 "$f $uf4 $first_packet_only" "$f $uf6 $first_packet_only" $QNUM_DHT4ALL
}
zapret_custom_firewall_nft()
@@ -31,8 +33,8 @@ zapret_custom_firewall_nft()
# stop logic is not required
local f
local first_packet_only="$nft_connbytes 1"
local first_packet_only=$(nft_first_packets $NFQWS_OPT_DHT_PKT_OUT)
f="meta length 109-407 meta l4proto udp @ih,0,16 0x6431"
f="udp length ge 13 meta l4proto udp @ih,0,16 0x6431-0x6432"
nft_fw_nfqws_post "$f $first_packet_only" "$f $first_packet_only" $QNUM_DHT4ALL
}

View File

@@ -1,30 +1,30 @@
# 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=* --payload known,unknown --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2:payload=all --new --filter-tcp=* --payload=known,unknown --lua-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}
NFQWS2_MY1_OPT="${NFQWS2_MY1_OPT:---filter-udp=* --payload known,unknown --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2:payload=all --new --filter-tcp=* --payload=known,unknown --lua-desync=multisplit}"
NFQWS2_MY1_SUBNETS4="${NFQWS2_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}"
NFQWS2_MY1_SUBNETS6="${NFQWS2_MY1_SUBNETS6:-2a00:1450::/29}"
NFQWS2_MY1_PORTS_TCP=${NFQWS2_MY1_PORTS_TCP:-$NFQWS2_PORTS_TCP}
NFQWS2_MY1_PORTS_UDP=${NFQWS2_MY1_PORTS_UDP:-$NFQWS2_PORTS_UDP}
NFQWS2_MY1_TCP_PKT_OUT=${NFQWS2_MY1_TCP_PKT_OUT:-$NFQWS2_TCP_PKT_OUT}
NFQWS2_MY1_UDP_PKT_OUT=${NFQWS2_MY1_UDP_PKT_OUT:-$NFQWS2_UDP_PKT_OUT}
NFQWS2_MY1_TCP_PKT_IN=${NFQWS2_MY1_TCP_PKT_IN:-$NFQWS2_TCP_PKT_IN}
NFQWS2_MY1_UDP_PKT_IN=${NFQWS2_MY1_UDP_PKT_IN:-$NFQWS2_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}"
NFQWS2_MY1_IPSET_SIZE=${NFQWS2_MY1_IPSET_SIZE:-4096}
NFQWS2_MY1_IPSET_OPT="${NFQWS2_MY1_IPSET_OPT:-hash:net hashsize 8192 maxelem $NFQWS2_MY1_IPSET_SIZE}"
alloc_dnum DNUM_NFQWS_MY1
alloc_qnum QNUM_NFQWS_MY1
NFQWS_MY1_NAME4=my1nfqws4
NFQWS_MY1_NAME6=my1nfqws6
alloc_dnum DNUM_NFQWS2_MY1
alloc_qnum QNUM_NFQWS2_MY1
NFQWS2_MY1_NAME4=my1nfqws4
NFQWS2_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"
local opt="--qnum=$QNUM_NFQWS2_MY1 $NFQWS2_MY1_OPT"
do_nfqws $1 $DNUM_NFQWS2_MY1 "$opt"
}
zapret_custom_firewall()
@@ -32,103 +32,103 @@ 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)
local NFQWS2_MY1_PORTS_TCP=$(replace_char - : $NFQWS2_MY1_PORTS_TCP)
local NFQWS2_MY1_PORTS_UDP=$(replace_char - : $NFQWS2_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
ipset create $NFQWS2_MY1_NAME4 $NFQWS2_MY1_IPSET_OPT family inet 2>/dev/null
ipset flush $NFQWS2_MY1_NAME4
for subnet in $NFQWS2_MY1_SUBNETS4; do
echo add $NFQWS2_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
ipset create $NFQWS2_MY1_NAME6 $NFQWS2_MY1_IPSET_OPT family inet6 2>/dev/null
ipset flush $NFQWS2_MY1_NAME6
for subnet in $NFQWS2_MY1_SUBNETS6; do
echo add $NFQWS2_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 "$NFQWS2_MY1_PORTS_TCP" ] && {
[ -n "$NFQWS2_MY1_TCP_PKT_OUT" -a "$NFQWS2_MY1_TCP_PKT_OUT" != 0 ] && {
f4="-p tcp -m multiport --dports $NFQWS2_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS2_MY1_TCP_PKT_OUT -m set --match-set"
f6="$f4 $NFQWS2_MY1_NAME6 dst"
f4="$f4 $NFQWS2_MY1_NAME4 dst"
fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS2_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 "$NFQWS2_MY1_TCP_PKT_IN" -a "$NFQWS2_MY1_TCP_PKT_IN" != 0 ] && {
f4="-p tcp -m multiport --sports $NFQWS2_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS2_MY1_TCP_PKT_IN -m set --match-set"
f6="$f4 $NFQWS2_MY1_NAME6 src"
f4="$f4 $NFQWS2_MY1_NAME4 src"
fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS2_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 "$NFQWS2_MY1_PORTS_UDP" ] && {
[ -n "$NFQWS2_MY1_UDP_PKT_OUT" -a "$NFQWS2_MY1_UDP_PKT_OUT" != 0 ] && {
f4="-p udp -m multiport --dports $NFQWS2_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS2_MY1_UDP_PKT_OUT -m set --match-set"
f6="$f4 $NFQWS2_MY1_NAME6 dst"
f4="$f4 $NFQWS2_MY1_NAME4 dst"
fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS2_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
[ -n "$NFQWS2_MY1_UDP_PKT_IN" -a "$NFQWS2_MY1_UDP_PKT_IN" != 0 ] && {
f4="-p udp -m multiport --sports $NFQWS2_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS2_MY1_UDP_PKT_IN -m set --match-set"
f6="$f4 $NFQWS2_MY1_NAME6 src"
f4="$f4 $NFQWS2_MY1_NAME4 src"
fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS2_MY1
}
}
[ "$1" = 1 ] || {
ipset destroy $NFQWS_MY1_NAME4 2>/dev/null
ipset destroy $NFQWS_MY1_NAME6 2>/dev/null
ipset destroy $NFQWS2_MY1_NAME4 2>/dev/null
ipset destroy $NFQWS2_MY1_NAME6 2>/dev/null
}
}
zapret_custom_firewall_nft()
{
local f4 f6 subnets
local first_packets_only="$nft_connbytes 1-$NFQWS_MY1_PKT_OUT"
local first_packets_only="$nft_connbytes 1-$NFQWS2_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"
make_comma_list subnets $NFQWS2_MY1_SUBNETS4
nft_create_set $NFQWS2_MY1_NAME4 "type ipv4_addr; size $NFQWS2_MY1_IPSET_SIZE; auto-merge; flags interval;"
nft_flush_set $NFQWS2_MY1_NAME4
nft_add_set_element $NFQWS2_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"
make_comma_list subnets $NFQWS2_MY1_SUBNETS6
nft_create_set $NFQWS2_MY1_NAME6 "type ipv6_addr; size $NFQWS2_MY1_IPSET_SIZE; auto-merge; flags interval;"
nft_flush_set $NFQWS2_MY1_NAME6
nft_add_set_element $NFQWS2_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 "$NFQWS2_MY1_PORTS_TCP" ] && {
[ -n "$NFQWS2_MY1_TCP_PKT_OUT" -a "$NFQWS2_MY1_TCP_PKT_OUT" != 0 ] && {
f4="tcp dport {$NFQWS2_MY1_PORTS_TCP} $(nft_first_packets $NFQWS2_MY1_TCP_PKT_OUT)"
f6="$f4 ip6 daddr @$NFQWS2_MY1_NAME6"
f4="$f4 ip daddr @$NFQWS2_MY1_NAME4"
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS2_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 "$NFQWS2_MY1_TCP_PKT_IN" -a "$NFQWS2_MY1_TCP_PKT_IN" != 0 ] && {
f4="tcp sport {$NFQWS2_MY1_PORTS_TCP} $(nft_first_packets $NFQWS2_MY1_TCP_PKT_IN)"
f6="$f4 ip6 saddr @$NFQWS2_MY1_NAME6"
f4="$f4 ip saddr @$NFQWS2_MY1_NAME4"
nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS2_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 "$NFQWS2_MY1_PORTS_UDP" ] && {
[ -n "$NFQWS2_MY1_UDP_PKT_OUT" -a "$NFQWS2_MY1_UDP_PKT_OUT" != 0 ] && {
f4="udp dport {$NFQWS2_MY1_PORTS_UDP} $(nft_first_packets $NFQWS2_MY1_UDP_PKT_OUT)"
f6="$f4 ip6 daddr @$NFQWS2_MY1_NAME6"
f4="$f4 ip daddr @$NFQWS2_MY1_NAME4"
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS2_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
[ -n "$NFQWS2_MY1_UDP_PKT_IN" -a "$NFQWS2_MY1_UDP_PKT_IN" != 0 ] && {
f4="udp sport {$NFQWS2_MY1_PORTS_UDP} $(nft_first_packets $NFQWS2_MY1_UDP_PKT_IN)"
f6="$f4 ip6 saddr @$NFQWS2_MY1_NAME6"
f4="$f4 ip saddr @$NFQWS2_MY1_NAME4"
nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS2_MY1
}
}
}
@@ -139,6 +139,6 @@ 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
nft_del_set $NFQWS2_MY1_NAME4 2>/dev/null
nft_del_set $NFQWS2_MY1_NAME6 2>/dev/null
}

View File

@@ -1,9 +1,9 @@
# this custom script runs desync to all wireguard handshake initiation packets
# this custom script runs desync to all wireguard handshake initiation, response and cookie 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:---payload wireguard_initiation --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
NFQWS_OPT_DESYNC_WG="${NFQWS_OPT_DESYNC_WG:---payload wireguard_initiation,wireguard_response,wireguard_cookie --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
alloc_dnum DNUM_WG4ALL
alloc_qnum QNUM_WG4ALL
@@ -21,7 +21,9 @@ 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
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=156&&0>>22&0x3C@8=0x01000000" "$f 44>>16=156&&48=0x01000000" $QNUM_WG4ALL
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=100&&0>>22&0x3C@8=0x02000000" "$f 44>>16=100&&48=0x02000000" $QNUM_WG4ALL
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=72&&0>>22&0x3C@8=0x03000000" "$f 44>>16=72&&48=0x03000000" $QNUM_WG4ALL
}
zapret_custom_firewall_nft()
{
@@ -29,4 +31,8 @@ zapret_custom_firewall_nft()
local f="udp length 156 @ih,0,32 0x01000000"
nft_fw_nfqws_post "$f" "$f" $QNUM_WG4ALL
local f="udp length 100 @ih,0,32 0x02000000"
nft_fw_nfqws_post "$f" "$f" $QNUM_WG4ALL
local f="udp length 72 @ih,0,32 0x03000000"
nft_fw_nfqws_post "$f" "$f" $QNUM_WG4ALL
}

View File

@@ -0,0 +1,62 @@
# this custom script feeds dns response data to main nfqws2 instance
# DISABLE_IPV{4,6} filters are not used intentionally. despite of not having wan ipv6 it's possible to query LAN DNS server over local ipv6
zapret_custom_firewall()
{
# $1 - 1 - run, 0 - stop
local filt="-p udp --sport 53"
local jump="-j NFQUEUE --queue-num $QNUM --queue-bypass"
local rule chain lan lanifs
get_lanif lanifs
# router
for lan in $lanifs; do
rule="-o $lan $filt $jump"
ipt_print_op $1 "$rule" "nfqws FORWARD (qnum $QNUM)"
ipt_add_del $1 FORWARD -t mangle $rule
ipt_print_op $1 "$rule" "nfqws FORWARD (qnum $QNUM)" 6
ipt6_add_del $1 FORWARD -t mangle $rule
done
# dns client server
for chain in INPUT OUTPUT ; do
rule="$filt $jump"
ipt_print_op $1 "$rule" "nfqws $chain (qnum $QNUM)"
ipt_add_del $1 $chain -t mangle $rule
ipt_print_op $1 "$rule" "nfqws $chain (qnum $QNUM)" 6
ipt6_add_del $1 $chain -t mangle $rule
done
}
zapret_custom_firewall_nft()
{
# stop logic is not required
local rule="udp sport 53 queue num $QNUM bypass"
# router
nft_print_op "oifname @lanif $rule" "nfqws forward (qnum $QNUM)" "4+6"
nft_add_chain forward_dns_feed "type filter hook forward priority mangle;"
nft_flush_chain forward_dns_feed
nft_add_rule forward_dns_feed oifname @lanif $rule
# dns client
nft_print_op "$rule" "nfqws input (qnum $QNUM)" "4+6"
nft_add_chain input_dns_feed "type filter hook input priority mangle;"
nft_flush_chain input_dns_feed
nft_add_rule input_dns_feed $rule
# dns server
nft_print_op "$rule" "nfqws output (qnum $QNUM)" "4+6"
nft_add_chain output_dns_feed "type filter hook output priority mangle;"
nft_flush_chain output_dns_feed
nft_add_rule output_dns_feed $rule
}
zapret_custom_firewall_nft_flush()
{
local chain
for chain in forward_dns_feed input_dns_feed output_dns_feed; do
nft_del_chain $chain 2>/dev/null
done
}

View File

@@ -0,0 +1,145 @@
# this custom script sets FILTER_MARK to specified source ips
# NOTE !!! SCRIPT REQUIRES FILTER_MARK VAR IN CONFIG FILE !!!
# NOTE !!! WITHOUT FILTER_MARK IT DOES NOTHING !!!
# NOTE !!! ON NON-OPENWRT SYSTEMS SCRIPT REQUIRES IFACE_LAN VAR IN CONFIG FILE !!!
# can override in config :
# LAN ip/cidr list to be fooled. elements are space separated
FILTER_LAN_IP="${FILTER_LAN_IP:-192.168.0.0/16}"
FILTER_LAN_IP6="${FILTER_LAN_IP6:-fc00::/7}"
# allow fooling from local system (0|1) ?
FILTER_LAN_ALLOW_OUTPUT="${FILTER_LAN_ALLOW_OUTPUT:-1}"
FILTER_LAN_SET="lanfilter"
FILTER_LAN_SET6="${FILTER_LAN_SET}6"
FILTER_LAN_IPSET_SIZE=${FILTER_LAN_IPSET_SIZE:-256}
FILTER_LAN_IPSET_OPT="${FILTER_LAN_IPSET_OPT:-hash:net hashsize 8192 maxelem $FILTER_LAN_IPSET_SIZE}"
filter_mark_check()
{
[ -n "$FILTER_MARK" ] || {
echo "WARNING ! lan filter cannot work without FILTER_MARK set in config"
return 1
}
[ "$DISABLE_IPV4" = 1 -a "$DISABLE_IPV6" = 1 ] && return 1
return 0
}
zapret_custom_firewall()
{
# $1 - 1 - run, 0 - stop
filter_mark_check || return
local subnet lanifs rule
local setmark="-j MARK --set-mark $FILTER_MARK/$FILTER_MARK"
local filt4="-m set --match-set $FILTER_LAN_SET src"
local filt6="-m set --match-set $FILTER_LAN_SET6 src"
get_lanif lanifs
[ "$DISABLE_IPV4" != 1 ] && {
[ "$FILTER_LAN_ALLOW_OUTPUT" = 1 ] && {
ipt_print_op $1 "$setmark" "filter output"
ipt_add_del $1 OUTPUT -t mangle $setmark
}
[ -n "$lanifs" ] && {
[ "$1" = 1 ] && {
ipset create $FILTER_LAN_SET $FILTER_LAN_IPSET_OPT family inet 2>/dev/null
ipset flush $FILTER_LAN_SET
for subnet in $FILTER_LAN_IP; do
echo add $FILTER_LAN_SET $subnet
done | ipset -! restore
}
for lan in $lanifs; do
rule="-i $lan $filt4 $setmark"
ipt_print_op $1 "$rule" "filter forward"
ipt_add_del $1 FORWARD -t mangle $rule
done
}
}
[ "$DISABLE_IPV6" != 1 ] && {
[ "$FILTER_LAN_ALLOW_OUTPUT" = 1 ] && {
ipt_print_op $1 "$setmark" "filter output" 6
ipt6_add_del $1 OUTPUT -t mangle $setmark
}
[ -n "$lanifs" ] && {
[ "$1" = 1 ] && {
ipset create $FILTER_LAN_SET6 $FILTER_LAN_IPSET_OPT family inet6 2>/dev/null
ipset flush $FILTER_LAN_SET6
for subnet in $FILTER_LAN_IP6; do
echo add $FILTER_LAN_SET6 $subnet
done | ipset -! restore
}
for lan in $lanifs; do
rule="-i $lan $filt6 $setmark"
ipt_print_op $1 "$rule" "filter forward" 6
ipt6_add_del $1 FORWARD -t mangle $rule
done
}
}
[ "$1" = 1 ] || {
ipset destroy $FILTER_LAN_SET 2>/dev/null
ipset destroy $FILTER_LAN_SET6 2>/dev/null
}
}
zapret_custom_firewall_nft()
{
filter_mark_check || return
local subnets rule
local setmark="meta mark set meta mark or $FILTER_MARK"
local filt4="ip saddr == @$FILTER_LAN_SET"
local filt6="ip6 saddr == @$FILTER_LAN_SET6"
local lanif="iifname @lanif"
nft_add_chain forward_lan_filter "type filter hook forward priority mangle;"
nft_flush_chain forward_lan_filter
if [ "$FILTER_LAN_ALLOW_OUTPUT" = 1 ]; then
nft_add_chain output_lan_filter "type filter hook output priority mangle;"
nft_flush_chain output_lan_filter
nft_print_op "$setmark" "filter output" "4+6"
nft_add_rule output_lan_filter $setmark
else
nft_del_chain output_lan_filter 2>/dev/null
fi
[ "$DISABLE_IPV4" != 1 ] && {
make_comma_list subnets $FILTER_LAN_IP
nft_create_set $FILTER_LAN_SET "type ipv4_addr; size $FILTER_LAN_IPSET_SIZE; auto-merge; flags interval;"
nft_flush_set $FILTER_LAN_SET
nft_add_set_element $FILTER_LAN_SET "$subnets"
rule="$lanif $filt4 $setmark"
nft_print_op "$rule" "filter forward" "4"
nft_add_rule forward_lan_filter $rule
}
[ "$DISABLE_IPV6" != 1 ] && {
make_comma_list subnets $FILTER_LAN_IP6
nft_create_set $FILTER_LAN_SET6 "type ipv6_addr; size $FILTER_LAN_IPSET_SIZE; auto-merge; flags interval;"
nft_flush_set $FILTER_LAN_SET6
nft_add_set_element $FILTER_LAN_SET6 "$subnets"
rule="$lanif $filt6 $setmark"
nft_print_op "$rule" "filter forward" "6"
nft_add_rule forward_lan_filter $rule
}
}
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_chain forward_lan_filter 2>/dev/null
nft_del_chain output_lan_filter 2>/dev/null
nft_del_set $FILTER_LAN_SET 2>/dev/null
nft_del_set $FILTER_LAN_SET6 2>/dev/null
}

View File

@@ -2,19 +2,6 @@
ZAPRET=/etc/init.d/zapret2
check_lan()
{
IS_LAN=
[ -n "$OPENWRT_LAN" ] || OPENWRT_LAN=lan
for lan in $OPENWRT_LAN; do
[ "$INTERFACE" = "$lan" ] && {
IS_LAN=1
break
}
done
}
[ -n "$INTERFACE" ] && [ "$ACTION" = ifup -o "$ACTION" = ifdown ] && [ -x "$ZAPRET" ] && "$ZAPRET" enabled && {
SCRIPT=$(readlink "$ZAPRET")
if [ -n "$SCRIPT" ]; then

View File

@@ -62,6 +62,20 @@ network_find_wanX_devices()
call_for_multiple_items network_get_device $2 "$ifaces"
}
get_wanif46()
{
# $1 - 4/6
# $2 - var to receive interface list
local ifaces
network_find_wan${1}_all ifaces
call_for_multiple_items network_get_device $2 "$ifaces"
}
get_lanif()
{
# $1 - var to receive interface list
call_for_multiple_items network_get_device $1 "$OPENWRT_LAN"
}
fw_nfqws_prepost_x()
{
@@ -71,10 +85,8 @@ fw_nfqws_prepost_x()
# $4 - 4/6
# $5 - post/pre
local ifaces DWAN
network_find_wan${4}_all ifaces
call_for_multiple_items network_get_device DWAN "$ifaces"
local DWAN
get_wanif46 $4 DWAN
[ -n "$DWAN" ] && _fw_nfqws_${5}${4} $1 "$2" $3 "$(unique $DWAN)"
}
fw_nfqws_post4()

View File

@@ -75,6 +75,26 @@ NFQWS2="${NFQWS2:-$ZAPRET_BASE/nfq2/nfqws2}"
LUAOPT="--lua-init=@$ZAPRET_BASE/lua/zapret-lib.lua --lua-init=@$ZAPRET_BASE/lua/zapret-antidpi.lua --lua-init=@$ZAPRET_BASE/lua/zapret-auto.lua"
NFQWS2_OPT_BASE="$USEROPT --fwmark=$DESYNC_MARK $LUAOPT"
get_wanif46()
{
# $1 - 4/6
# $2 - var to receive interface list
case $1 in
6)
eval $2="\${IFACE_WAN6:-$IFACE_WAN}"
;;
4)
eval $2="\$IFACE_WAN"
;;
*)
eval $2=
esac
}
get_lanif()
{
# $1 - var to receive interface list
eval $1="\$IFACE_LAN"
}
fw_nfqws_post4()
{
@@ -119,7 +139,7 @@ nft_wanif6_filter_present()
}
nft_fill_ifsets_overload()
{
nft_fill_ifsets "$IFACE_WAN" "${IFACE_WAN6:-$IFACE_WAN}" "$IFACE_LAN"
nft_fill_ifsets "$IFACE_LAN" "$IFACE_WAN" "${IFACE_WAN6:-$IFACE_WAN}"
}

View File

@@ -0,0 +1 @@
udp.Length>=5 and udp.Payload[0]=0x64 and udp.Payload[1]>=0x31 and udp.Payload[1]<=0x32

View File

@@ -1,4 +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
udp.Payload[1]=0 and udp.Payload16[1]=0 and udp.Payload[4]=1

View File

@@ -1,3 +1,3 @@
outbound and
udp.PayloadLength=148 and
udp.Payload[0]=0x01
udp.PayloadLength=148 and udp.Payload32[0]=0x01000000 or
udp.PayloadLength=92 and udp.Payload32[0]=0x02000000 or
udp.PayloadLength=64 and udp.Payload32[0]=0x03000000

View File

@@ -31,7 +31,7 @@ select_test_method()
elif exists zsh && [ "$UNAME" != CYGWIN ] ; then
TEST=zsh
elif [ "$UNAME" != CYGWIN ]; then
if exists hexdump and exists dd; then
if exists hexdump && exists dd; then
# macos does not use ELF
TEST=elf
ELF=

View File

@@ -233,10 +233,10 @@ select_getlist()
echo
if ask_yes_no $D "do you want to auto download ip/host list"; then
if [ "$MODE_FILTER" = "hostlist" -o "$MODE_FILTER" = "autohostlist" ] ; then
GETLISTS="get_refilter_domains.sh get_antizapret_domains.sh get_reestr_resolvable_domains.sh get_reestr_hostlist.sh"
GETLISTS="get_refilter_domains.sh get_antizapret_domains.sh get_reestr_resolvable_domains.sh"
GETLIST_DEF="get_antizapret_domains.sh"
else
GETLISTS="get_user.sh get_refilter_ipsum.sh get_antifilter_ip.sh get_antifilter_ipsmart.sh get_antifilter_ipsum.sh get_antifilter_ipresolve.sh get_antifilter_allyouneed.sh get_reestr_resolve.sh get_reestr_preresolved.sh get_reestr_preresolved_smart.sh"
GETLISTS="get_user.sh get_refilter_ipsum.sh get_antifilter_ip.sh get_antifilter_ipsmart.sh get_antifilter_ipsum.sh get_antifilter_ipresolve.sh get_antifilter_allyouneed.sh get_reestr_preresolved.sh get_reestr_preresolved_smart.sh"
GETLIST_DEF="get_antifilter_allyouneed.sh"
fi
ask_list GETLIST "$GETLISTS" "$GETLIST_DEF" && write_config_var GETLIST
@@ -601,7 +601,7 @@ check_dns()
install_systemd()
{
INIT_SCRIPT_SRC="$EXEDIR/init.d/sysv/zapret"
INIT_SCRIPT_SRC="$EXEDIR/init.d/sysv/zapret2"
CUSTOM_DIR="$ZAPRET_RW/init.d/sysv"
check_bins

View File

@@ -49,7 +49,7 @@ static int ucmp(const void * a, const void * b, void *arg)
}
static uint32_t mask_from_bitcount(uint32_t zct)
{
return zct<32 ? ~((1 << zct) - 1) : 0;
return zct<32 ? ~((1u << zct) - 1) : 0;
}
// make presorted array unique. return number of unique items.
// 1,1,2,3,3,0,0,0 (ct=8) => 1,2,3,0 (ct=4)
@@ -138,7 +138,7 @@ static void mask_from_bitcount6_make(uint32_t zct, struct in6_addr *a)
int32_t n = (127 - zct) >> 3;
memset(a->s6_addr,0xFF,n);
memset(a->s6_addr+n,0x00,16-n);
a->s6_addr[n] = ~((1 << (zct & 7)) - 1);
a->s6_addr[n] = ~((1u << (zct & 7)) - 1);
}
}
static struct in6_addr ip6_mask[129];

View File

@@ -68,7 +68,6 @@ ipset_restore()
{
# $1 - ipset name
# $2 - filename
zzexist "$2" || return
local fsize=$(zzsize "$2")
local svram=0
@@ -77,7 +76,7 @@ ipset_restore()
local T="Adding to ipset $1 "
[ "$svram" = "1" ] && T="$T (saveram)"
T="$T : $f"
T="$T : $2"
echo $T
if [ "$svram" = "1" ]; then

View File

@@ -44,7 +44,9 @@ ZUSERLIST_EXCLUDE="$IPSET_RW_DIR/zapret-hosts-user-exclude.txt"
[ -n "$IP2NET" ] || IP2NET="$ZAPRET_BASE/ip2net/ip2net"
[ -n "$MDIG" ] || MDIG="$ZAPRET_BASE/mdig/mdig"
[ -z "$MDIG_THREADS" ] && MDIG_THREADS=30
MDIG_THREADS=${MDIG_THREADS:-30}
MDIG_EAGAIN=${MDIG_EAGAIN:-10}
MDIG_EAGAIN_DELAY=${MDIG_EAGAIN_DELAY:-500}
@@ -124,7 +126,7 @@ zzcat()
zz()
{
if [ "$GZIP_LISTS" = "1" ]; then
gzip -c >"$1.gz"
gzip -9c >"$1.gz"
rm -f "$1"
else
cat >"$1"
@@ -161,7 +163,7 @@ digger()
if [ -x "$MDIG" ]; then
local cmd
[ "$2" = "s" ] && cmd=--stats=1000
"$MDIG" --family=$1 --threads=$MDIG_THREADS $cmd
"$MDIG" --family=$1 --threads=$MDIG_THREADS --eagain=$MDIG_EAGAIN --eagain-delay=$MDIG_EAGAIN_DELAY $cmd
else
local A=A
[ "$1" = "6" ] && A=AAAA
@@ -272,11 +274,10 @@ hup_zapret_daemons()
{
echo forcing zapret daemons to reload their hostlist
if exists killall; then
killall -HUP tpws nfqws dvtws 2>/dev/null
killall -HUP nfqws2 dvtws2 2>/dev/null
elif exists pkill; then
pkill -HUP ^tpws$
pkill -HUP ^nfqws$
pkill -HUP ^dvtws$
pkill -HUP ^nfqws2$
pkill -HUP ^dvtws2$
else
echo no mass killer available ! cant HUP zapret daemons
fi

View File

@@ -1,65 +0,0 @@
#!/bin/sh
IPSET_DIR="$(dirname "$0")"
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
. "$IPSET_DIR/def.sh"
ZREESTR="$TMPDIR/zapret.txt.gz"
IPB="$TMPDIR/ipb.txt"
ZURL_REESTR=https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv.gz
dl_checked()
{
# $1 - url
# $2 - file
# $3 - minsize
# $4 - maxsize
# $5 - maxtime
curl -k --fail --max-time $5 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$2" "$1" ||
{
echo list download failed : $1
return 2
}
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
fi
return 0
}
reestr_list()
{
LC_ALL=C LANG=C gunzip -c "$ZREESTR" | cut -s -f2 -d';' | LC_ALL=C LANG=C nice -n 5 sed -Ee 's/^\*\.(.+)$/\1/' -ne 's/^[a-z0-9A-Z._-]+$/&/p' | $AWK '{ print tolower($0) }'
}
reestr_extract_ip()
{
LC_ALL=C LANG=C gunzip -c | nice -n 5 $AWK -F ';' '($1 ~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/) && (($2 == "" && $3 == "") || ($1 == $2)) {gsub(/ \| /, RS); print $1}' | LC_ALL=C LANG=C $AWK '{split($1, a, /\|/); for (i in a) {print a[i]}}'
}
ipban_fin()
{
getipban
"$IPSET_DIR/create_ipset.sh"
}
dl_checked "$ZURL_REESTR" "$ZREESTR" 204800 251658240 600 || {
ipban_fin
exit 2
}
reestr_list | sort -u | zz "$ZHOSTLIST"
reestr_extract_ip <"$ZREESTR" >"$IPB"
rm -f "$ZREESTR"
[ "$DISABLE_IPV4" != "1" ] && $AWK '/^([0-9]{1,3}\.){3}[0-9]{1,3}($|(\/[0-9]{2}$))/' "$IPB" | cut_local | ip2net4 | zz "$ZIPLIST_IPBAN"
[ "$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

@@ -10,8 +10,8 @@ TMPLIST="$TMPDIR/list.txt"
BASEURL="https://raw.githubusercontent.com/bol-van/rulist/main"
URL4="$BASEURL/reestr_resolved4.txt"
URL6="$BASEURL/reestr_resolved6.txt"
IPB4="$BASEURL/reestr_ipban4.txt"
IPB6="$BASEURL/reestr_ipban6.txt"
#IPB4="$BASEURL/reestr_ipban4.txt"
#IPB6="$BASEURL/reestr_ipban6.txt"
dl()
{
@@ -35,12 +35,12 @@ dl()
getuser && {
[ "$DISABLE_IPV4" != "1" ] && {
dl "$URL4" "$ZIPLIST" 32768 4194304
dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576
dl "$URL4" "$ZIPLIST" 4096 4194304
# dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576
}
[ "$DISABLE_IPV6" != "1" ] && {
dl "$URL6" "$ZIPLIST6" 8192 4194304
dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576
dl "$URL6" "$ZIPLIST6" 2048 4194304
# dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576
}
}

View File

@@ -10,8 +10,8 @@ TMPLIST="$TMPDIR/list.txt"
BASEURL="https://raw.githubusercontent.com/bol-van/rulist/main"
URL4="$BASEURL/reestr_smart4.txt"
URL6="$BASEURL/reestr_smart6.txt"
IPB4="$BASEURL/reestr_ipban4.txt"
IPB6="$BASEURL/reestr_ipban6.txt"
#IPB4="$BASEURL/reestr_ipban4.txt"
#IPB6="$BASEURL/reestr_ipban6.txt"
dl()
{
@@ -35,12 +35,12 @@ dl()
getuser && {
[ "$DISABLE_IPV4" != "1" ] && {
dl "$URL4" "$ZIPLIST" 32768 4194304
dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576
dl "$URL4" "$ZIPLIST" 4096 4194304
# dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576
}
[ "$DISABLE_IPV6" != "1" ] && {
dl "$URL6" "$ZIPLIST6" 8192 4194304
dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576
dl "$URL6" "$ZIPLIST6" 2048 4194304
# dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576
}
}

View File

@@ -9,8 +9,8 @@ TMPLIST="$TMPDIR/list_nethub.txt"
BASEURL="https://raw.githubusercontent.com/bol-van/rulist/main"
URL="$BASEURL/reestr_hostname_resolvable.txt"
IPB4="$BASEURL/reestr_ipban4.txt"
IPB6="$BASEURL/reestr_ipban6.txt"
#IPB4="$BASEURL/reestr_ipban4.txt"
#IPB6="$BASEURL/reestr_ipban6.txt"
dl()
{
@@ -36,8 +36,8 @@ 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
#[ "$DISABLE_IPV4" != "1" ] && dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576
#[ "$DISABLE_IPV6" != "1" ] && dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576
getipban
"$IPSET_DIR/create_ipset.sh"

View File

@@ -1,83 +0,0 @@
#!/bin/sh
IPSET_DIR="$(dirname "$0")"
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
. "$IPSET_DIR/def.sh"
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.gz
dl_checked()
{
# $1 - url
# $2 - file
# $3 - minsize
# $4 - maxsize
# $5 - maxtime
curl -k --fail --max-time $5 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$2" "$1" ||
{
echo list download failed : $1
return 2
}
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
fi
return 0
}
reestr_list()
{
LC_ALL=C LANG=C gunzip -c "$ZREESTR" | cut -s -f2 -d';' | LC_ALL=C LANG=C nice -n 5 sed -Ee 's/^\*\.(.+)$/\1/' -ne 's/^[a-z0-9A-Z._-]+$/&/p' | $AWK '{ print tolower($0) }'
}
reestr_extract_ip()
{
LC_ALL=C LANG=C gunzip -c | nice -n 5 $AWK -F ';' '($1 ~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/) && (($2 == "" && $3 == "") || ($1 == $2)) {gsub(/ \| /, RS); print $1}' | LC_ALL=C LANG=C $AWK '{split($1, a, /\|/); for (i in a) {print a[i]}}'
}
getuser && {
# both disabled
[ "$DISABLE_IPV4" = "1" ] && [ "$DISABLE_IPV6" = "1" ] && exit 0
dl_checked "$ZURL_REESTR" "$ZREESTR" 204800 251658240 600 || exit 2
echo preparing ipban list ..
reestr_extract_ip <"$ZREESTR" >"$IPB"
[ "$DISABLE_IPV4" != "1" ] && $AWK '/^([0-9]{1,3}\.){3}[0-9]{1,3}($|(\/[0-9]{2}$))/' "$IPB" | cut_local | ip2net4 | zz "$ZIPLIST_IPBAN"
[ "$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"
echo preparing dig list ..
reestr_list | sort -u >"$ZDIG"
rm -f "$ZREESTR"
echo digging started. this can take long ...
[ "$DISABLE_IPV4" != "1" ] && {
filedigger "$ZDIG" 4 | cut_local >"$ZIPLISTTMP" || {
rm -f "$ZDIG"
exit 1
}
ip2net4 <"$ZIPLISTTMP" | zz "$ZIPLIST"
rm -f "$ZIPLISTTMP"
}
[ "$DISABLE_IPV6" != "1" ] && {
filedigger "$ZDIG" 6 | cut_local6 >"$ZIPLISTTMP" || {
rm -f "$ZDIG"
exit 1
}
ip2net6 <"$ZIPLISTTMP" | zz "$ZIPLIST6"
rm -f "$ZIPLISTTMP"
}
rm -f "$ZDIG"
}
"$IPSET_DIR/create_ipset.sh"

View File

@@ -149,12 +149,17 @@ function http_hostcase(ctx, desync)
error("http_hostcase: invalid host spelling '"..spell.."'")
else
local hdis = http_dissect_req(desync.dis.payload)
if hdis.headers.host then
DLOG("http_hostcase: 'Host:' => '"..spell.."'")
desync.dis.payload = string.sub(desync.dis.payload,1,hdis.headers.host.pos_start-1)..spell..string.sub(desync.dis.payload,hdis.headers.host.pos_header_end+1)
return VERDICT_MODIFY
if hdis then
local idx_host = array_field_search(hdis.headers, "header_low", "host")
if idx_host then
DLOG("http_hostcase: 'Host:' => '"..spell.."'")
desync.dis.payload = string.sub(desync.dis.payload,1,hdis.headers[idx_host].pos_start-1)..spell..string.sub(desync.dis.payload,hdis.headers[idx_host].pos_header_end+1)
return VERDICT_MODIFY
else
DLOG("http_hostcase: 'Host:' header not found")
end
else
DLOG("http_hostcase: 'Host:' header not found")
DLOG("http_hostcase: http dissect error")
end
end
end
@@ -162,6 +167,7 @@ end
-- nfqws1 : "--methodeol"
-- standard args : direction
-- NOTE : if using with other http tampering methodeol should be the last !
function http_methodeol(ctx, desync)
if not desync.dis.tcp then
instance_cutoff_shim(ctx, desync)
@@ -170,17 +176,57 @@ function http_methodeol(ctx, desync)
direction_cutoff_opposite(ctx, desync)
if desync.l7payload=="http_req" and direction_check(desync) then
local hdis = http_dissect_req(desync.dis.payload)
local ua = hdis.headers["user-agent"]
if ua then
if (ua.pos_end - ua.pos_value_start) < 2 then
DLOG("http_methodeol: 'User-Agent:' header is too short")
if hdis then
local idx_ua = array_field_search(hdis.headers, "header_low", "user-agent")
if idx_ua then
local ua = hdis.headers[idx_ua]
if (ua.pos_end - ua.pos_value_start) < 2 then
DLOG("http_methodeol: 'User-Agent:' header is too short")
else
DLOG("http_methodeol: applied")
desync.dis.payload="\r\n"..string.sub(desync.dis.payload,1,ua.pos_end-2)..(string.sub(desync.dis.payload,ua.pos_end+1) or "");
return VERDICT_MODIFY
end
else
DLOG("http_methodeol: applied")
desync.dis.payload="\r\n"..string.sub(desync.dis.payload,1,ua.pos_end-2)..(string.sub(desync.dis.payload,ua.pos_end+1) or "");
return VERDICT_MODIFY
DLOG("http_methodeol: 'User-Agent:' header not found")
end
else
DLOG("http_methodeol: 'User-Agent:' header not found")
DLOG("http_methodeol: http dissect error")
end
end
end
-- nfqws1 : not available
-- tpws : --unixeol
-- standard args : direction
function http_unixeol(ctx, desync)
if not desync.dis.tcp then
instance_cutoff_shim(ctx, desync)
return
end
direction_cutoff_opposite(ctx, desync)
if desync.l7payload=="http_req" and direction_check(desync) then
local hdis = http_dissect_req(desync.dis.payload)
if hdis then
local idx_ua = array_field_search(hdis.headers, "header_low", "user-agent")
if idx_ua then
local http = http_reconstruct_req(hdis, true)
if #http < #desync.dis.payload then
hdis.headers[idx_ua].value = hdis.headers[idx_ua].value .. string.rep(" ", #desync.dis.payload - #http)
end
local http = http_reconstruct_req(hdis, true)
if #http==#desync.dis.payload then
desync.dis.payload = http
DLOG("http_unixeol: applied")
return VERDICT_MODIFY
else
DLOG("http_unixeol: reconstruct differs in size from original: "..#http.."!="..#desync.dis.payload)
end
else
DLOG("http_unixeol: 'User-Agent:' header absent")
end
else
DLOG("http_unixeol: could not dissect http")
end
end
end
@@ -287,10 +333,43 @@ function wssize(ctx, desync)
return verdict
end
-- nfqws1 : not available
-- standard args : direction
-- arg: blob - blob name to store cloned tls client hello (stored in desync, not global)
-- arg: fallback - copy this blob if could not clone
-- arg: sni_snt - server name type value in existing names
-- arg: sni_snt_new - server name type value for new names
-- arg: sni_del_ext - delete sni extension
-- arg: sni_del - delete all names
-- arg: sni_first - add name to the beginning
-- arg: sni_last - add name to the end
function tls_client_hello_clone(ctx, desync)
if not desync.dis.tcp then
instance_cutoff_shim(ctx, desync)
return
end
direction_cutoff_opposite(ctx, desync)
if direction_check(desync) then
if not desync.arg.blob then
error("tls_client_hello_clone: 'blob' arg required")
end
if desync.l7payload=="tls_client_hello" then
desync[desync.arg.blob] = tls_client_hello_mod(desync.reasm_data or desync.dis.payload, desync.arg)
if desync[desync.arg.blob] then
DLOG("tls_client_hello_clone: cloned to desync."..desync.arg.blob)
end
end
if not desync[desync.arg.blob] and desync.arg.fallback then
DLOG("tls_client_hello_clone: desync."..desync.arg.blob.."="..desync.arg.fallback)
desync[desync.arg.blob] = blob(desync, desync.arg.fallback)
end
end
end
-- nfqws1 : "--dpi-desync=syndata"
-- standard args : fooling, rawsend, reconstruct, ipfrag
-- arg : blob=<blob> - fake payload. must fit to single packet. no segmentation possible. default - 16 zero bytes.
-- arg : tls_mod=<list> - comma separated list of tls mods : rnd,rndsni,sni=<str>
-- arg : tls_mod=<list> - comma separated list of tls mods : rnd,rndsni,sni=<str>. sni=%var is supported
function syndata(ctx, desync)
if desync.dis.tcp then
if bitand(desync.dis.tcp.th_flags, TH_SYN + TH_ACK)==TH_SYN then
@@ -298,7 +377,7 @@ function syndata(ctx, desync)
dis.payload = blob(desync, desync.arg.blob, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
apply_fooling(desync, dis)
if desync.arg.tls_mod then
dis.payload = tls_mod(dis.payload, desync.arg.tls_mod, nil)
dis.payload = tls_mod_shim(desync, dis.payload, desync.arg.tls_mod, nil)
end
if b_debug then DLOG("syndata: "..hexdump_dlog(dis.payload)) end
if rawsend_dissect_ipfrag(dis, desync_opts(desync)) then
@@ -340,7 +419,8 @@ end
-- nfqws1 : "--dpi-desync=fake"
-- standard args : direction, payload, fooling, ip_id, rawsend, reconstruct, ipfrag
-- arg : blob=<blob> - fake payload
-- arg : tls_mod=<list> - comma separated list of tls mods : rnd,rndsni,sni=<str>,dupsid,padencap
-- arg : optional - skip if blob is absent
-- arg : tls_mod=<list> - comma separated list of tls mods : rnd,rndsni,sni=<str>,dupsid,padencap . sni=%var is supported
function fake(ctx, desync)
direction_cutoff_opposite(ctx, desync)
-- by default process only outgoing known payloads
@@ -349,9 +429,13 @@ function fake(ctx, desync)
if not desync.arg.blob then
error("fake: 'blob' arg required")
end
if desync.arg.optional and not blob_exist(desync, desync.arg.blob) then
DLOG("fake: blob '"..desync.arg.blob.."' not found. skipped")
return
end
local fake_payload = blob(desync, desync.arg.blob)
if desync.reasm_data and desync.arg.tls_mod then
fake_payload = tls_mod(fake_payload, desync.arg.tls_mod, desync.reasm_data)
fake_payload = tls_mod_shim(desync, fake_payload, desync.arg.tls_mod, desync.reasm_data)
end
-- check debug to save CPU
if b_debug then DLOG("fake: "..hexdump_dlog(fake_payload)) end
@@ -368,6 +452,7 @@ end
-- arg : seqovl=N . decrease seq number of the first segment by N and fill N bytes with pattern (default - all zero)
-- arg : seqovl_pattern=<blob> . override pattern
-- arg : blob=<blob> - use this data instead of desync.dis.payload
-- arg : optional - skip if blob is absent. use zero pattern if seqovl_pattern blob is absent
-- arg : nodrop - do not drop current dissect
function multisplit(ctx, desync)
if not desync.dis.tcp then
@@ -375,7 +460,10 @@ function multisplit(ctx, desync)
return
end
direction_cutoff_opposite(ctx, desync)
-- by default process only outgoing known payloads
if desync.arg.optional and desync.arg.blob and not blob_exist(desync, desync.arg.blob) then
DLOG("multisplit: blob '"..desync.arg.blob.."' not found. skipped")
return
end
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
if #data>0 and direction_check(desync) and payload_check(desync) then
if replay_first(desync) then
@@ -393,7 +481,14 @@ function multisplit(ctx, desync)
local seqovl=0
if i==0 and desync.arg.seqovl and tonumber(desync.arg.seqovl)>0 then
seqovl = tonumber(desync.arg.seqovl)
local pat = desync.arg.seqovl_pattern and blob(desync,desync.arg.seqovl_pattern) or "\x00"
local pat="\x00"
if desync.arg.seqovl_pattern then
if desync.arg.optional and not blob_exist(desync, desync.arg.seqovl_pattern) then
DLOG("multisplit: blob '"..desync.arg.seqovl_pattern.."' not found. using zero pattern")
else
pat = blob(desync,desync.arg.seqovl_pattern)
end
end
part = pattern(pat,1,seqovl)..part
end
if b_debug then DLOG("multisplit: sending part "..(i+1).." "..(pos_start-1).."-"..(pos_end-1).." len="..#part.." seqovl="..seqovl.." : "..hexdump_dlog(part)) end
@@ -416,12 +511,62 @@ function multisplit(ctx, desync)
end
end
-- internal function for code deduplication. do not call directly
function pos_normalize(pos, low, hi)
return (pos>=low and pos<hi) and (pos-low+1) or nil
end
-- internal function for code deduplication. do not call directly
function pos_array_normalize(pos, low, hi)
-- remove positions outside of hi,low range. normalize others to low
local i=1
while i<=#pos do
pos[i] = pos_normalize(pos[i], low, hi)
if pos[i] then
i = i + 1
else
table.remove(pos, i);
end
end
end
-- internal function for code deduplication. do not call directly
function multidisorder_send(desync, data, seqovl, pos)
for i=#pos,0,-1 do
local pos_start = pos[i] or 1
local pos_end = i<#pos and pos[i+1]-1 or #data
local part = string.sub(data,pos_start,pos_end)
local ovl=0
if i==1 and seqovl and seqovl>0 then
if seqovl>=pos[1] then
DLOG("multidisorder: seqovl cancelled because seqovl "..(seqovl-1).." is not less than the first split pos "..(pos[1]-1))
else
ovl = seqovl - 1
local pat="\x00"
if desync.arg.seqovl_pattern then
if desync.arg.optional and not blob_exist(desync, desync.arg.seqovl_pattern) then
DLOG("multidisorder: blob '"..desync.arg.seqovl_pattern.."' not found. using zero pattern")
else
pat = blob(desync,desync.arg.seqovl_pattern)
end
end
part = pattern(pat,1,ovl)..part
end
end
if b_debug then DLOG("multidisorder: sending part "..(i+1).." "..(pos_start-1).."-"..(pos_end-1).." len="..#part.." seqovl="..ovl.." : "..hexdump_dlog(part)) end
if not rawsend_payload_segmented(desync,part,pos_start-1-ovl) then
return VERDICT_PASS
end
end
return VERDICT_DROP
end
-- nfqws1 : "--dpi-desync=multidisorder"
-- algorithm is not 100% the same as in nfqws1. multi-segment queries can produce different segment ordering.
-- standard args : direction, payload, fooling, ip_id, rawsend, reconstruct, ipfrag
-- arg : pos=<postmarker list> . position marker list. example : "1,host,midsld+1,-10"
-- arg : seqovl=N . decrease seq number of the second segment in the original order by N and fill N bytes with pattern (default - all zero). N must be less than the first split pos.
-- arg : seqovl_pattern=<blob> . override pattern
-- arg : blob=<blob> - use this data instead of desync.dis.payload
-- arg : blob=<blob> - use this data instead of reasm_data
-- arg : optional - skip if blob is absent. use zero pattern if seqovl_pattern blob is absent
-- arg : nodrop - do not drop current dissect
function multidisorder(ctx, desync)
if not desync.dis.tcp then
@@ -429,7 +574,10 @@ function multidisorder(ctx, desync)
return
end
direction_cutoff_opposite(ctx, desync)
-- by default process only outgoing known payloads
if desync.arg.optional and desync.arg.blob and not blob_exist(desync, desync.arg.blob) then
DLOG("multidisorder: blob '"..desync.arg.blob.."' not found. skipped")
return
end
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
if #data>0 and direction_check(desync) and payload_check(desync) then
if replay_first(desync) then
@@ -440,32 +588,16 @@ function multidisorder(ctx, desync)
if b_debug then DLOG("multidisorder: resolved split pos: "..table.concat(zero_based_pos(pos)," ")) end
delete_pos_1(pos) -- cannot split at the first byte
if #pos>0 then
for i=#pos,0,-1 do
local pos_start = pos[i] or 1
local pos_end = i<#pos and pos[i+1]-1 or #data
local part = string.sub(data,pos_start,pos_end)
local seqovl=0
if i==1 and desync.arg.seqovl then
seqovl = resolve_pos(data, desync.l7payload, desync.arg.seqovl)
if not seqovl then
DLOG("multidisorder: seqovl cancelled because could not resolve marker '"..desync.arg.seqovl.."'")
seqovl = 0
else
seqovl = seqovl - 1
if seqovl>=(pos[1]-1) then
DLOG("multidisorder: seqovl cancelled because seqovl "..seqovl.." is not less than the first split pos "..(pos[1]-1))
seqovl = 0
else
local pat = desync.arg.seqovl_pattern and blob(desync,desync.arg.seqovl_pattern) or "\x00"
part = pattern(pat,1,seqovl)..part
end
end
end
if b_debug then DLOG("multidisorder: sending part "..(i+1).." "..(pos_start-1).."-"..(pos_end-1).." len="..#part.." seqovl="..seqovl.." : "..hexdump_dlog(part)) end
if not rawsend_payload_segmented(desync,part,pos_start-1-seqovl) then
return VERDICT_PASS
local seqovl
if desync.arg.seqovl then
seqovl = resolve_pos(data, desync.l7payload, desync.arg.seqovl)
if not seqovl then
DLOG("multidisorder: seqovl cancelled because could not resolve marker '"..desync.arg.seqovl.."'")
end
end
if multidisorder_send(desync, data, seqovl, pos)==VERDICT_PASS then
return VERDICT_PASS
end
replay_drop_set(desync)
return desync.arg.nodrop and VERDICT_PASS or VERDICT_DROP
else
@@ -481,6 +613,60 @@ function multidisorder(ctx, desync)
end
end
-- nfqws1 : "--dpi-desync=multidisorder". segment ordering is the same as in nfqws1
-- standard args : direction, payload, fooling, ip_id, rawsend, reconstruct, ipfrag
-- arg : pos=<postmarker list> . position marker list. example : "1,host,midsld+1,-10"
-- arg : seqovl=N . decrease seq number of the second segment in the original order by N and fill N bytes with pattern (default - all zero). N must be less than the first split pos.
-- arg : seqovl_pattern=<blob> . override pattern
-- arg : optional - use zero pattern if seqovl_pattern blob is absent
function multidisorder_legacy(ctx, desync)
if not desync.dis.tcp then
instance_cutoff_shim(ctx, desync)
return
end
direction_cutoff_opposite(ctx, desync)
-- by default process only outgoing known payloads
local data = desync.dis.payload
local fulldata = desync.reasm_data
if #data>0 and direction_check(desync) and payload_check(desync) then
local range_low = (desync.reasm_offset or 0) + 1
local range_hi = range_low + #data
local spos = desync.arg.pos or "2"
-- check debug to save CPU
if b_debug then DLOG("multidisorder_legacy: split pos: "..spos) end
local pos = resolve_multi_pos(fulldata, desync.l7payload, spos)
if b_debug then DLOG("multidisorder_legacy: resolved split pos: "..table.concat(zero_based_pos(pos)," ")) end
DLOG("multidisorder_legacy: reasm piece range: "..(range_low-1).."-"..(range_hi-2))
pos_array_normalize(pos, range_low, range_hi)
delete_pos_1(pos) -- cannot split at the first byte
if #pos>0 then
if b_debug then DLOG("multidisorder_legacy: normalized split pos: "..table.concat(zero_based_pos(pos)," ")) end
local seqovl
if desync.arg.seqovl then
seqovl = resolve_pos(fulldata, desync.l7payload, desync.arg.seqovl)
if seqovl then
DLOG("multidisorder_legacy: resolved seqovl pos: "..(seqovl-1))
seqovl = pos_normalize(seqovl, range_low, range_hi)
if seqovl then
DLOG("multidisorder_legacy: normalized seqovl pos: "..(seqovl-1))
else
DLOG("multidisorder_legacy: normalized seqovl pos is outside of the reasm piece range")
end
else
DLOG("multidisorder_legacy: seqovl cancelled because could not resolve marker '"..desync.arg.seqovl.."'")
end
end
return multidisorder_send(desync, data, seqovl, pos)
else
DLOG("multidisorder_legacy: no normalized split pos in this packet")
-- send as is with applied options
if rawsend_payload_segmented(desync) then
return VERDICT_DROP
end
end
end
end
-- nfqws1 : "--dpi-desync=hostfakesplit"
-- standard args : direction, payload, fooling, ip_id, rawsend, reconstruct. FOOLING AND REPEATS APPLIED ONLY TO FAKES.
-- arg : host=<str> - hostname template. generate hosts like "random.template". example : e8nzn.vk.com
@@ -488,6 +674,7 @@ end
-- arg : nofake1, nofake2 - do not send individual fakes
-- arg : disorder_after=<posmarker> - send after_host part in 2 disordered segments. if posmarker is empty string use marker "-1"
-- arg : blob=<blob> - use this data instead of desync.dis.payload
-- arg : optional - skip if blob is absent
-- arg : nodrop - do not drop current dissect
function hostfakesplit(ctx, desync)
if not desync.dis.tcp then
@@ -495,7 +682,10 @@ function hostfakesplit(ctx, desync)
return
end
direction_cutoff_opposite(ctx, desync)
-- by default process only outgoing known payloads
if desync.arg.optional and desync.arg.blob and not blob_exist(desync, desync.arg.blob) then
DLOG("hostfakesplit: blob '"..desync.arg.blob.."' not found. skipped")
return
end
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
if #data>0 and direction_check(desync) and payload_check(desync) then
if replay_first(desync) then
@@ -600,7 +790,8 @@ end
-- arg : pattern=<blob> . fill fake parts with this pattern
-- arg : seqovl=N . decrease seq number of the first segment by N and fill N bytes with pattern (default - all zero)
-- arg : seqovl_pattern=<blob> . override seqovl pattern
-- arg : blob=<blob> - use this data instead of desync.dis.payload
-- arg : blob=<blob> - use this data instead of reasm_data
-- arg : optional - skip if blob is absent. use zero pattern if seqovl_pattern blob is absent
-- arg : nodrop - do not drop current dissect
function fakedsplit(ctx, desync)
if not desync.dis.tcp then
@@ -608,7 +799,10 @@ function fakedsplit(ctx, desync)
return
end
direction_cutoff_opposite(ctx, desync)
-- by default process only outgoing known payloads
if desync.arg.optional and desync.arg.blob and not blob_exist(desync, desync.arg.blob) then
DLOG("fakedsplit: blob '"..desync.arg.blob.."' not found. skipped")
return
end
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
if #data>0 and direction_check(desync) and payload_check(desync) then
if replay_first(desync) then
@@ -616,7 +810,7 @@ function fakedsplit(ctx, desync)
local pos = resolve_pos(data, desync.l7payload, spos)
if pos then
if pos == 1 then
DLOG("multidisorder: split pos resolved to 0. cannot split.")
DLOG("fakedsplit: split pos resolved to 0. cannot split.")
else
if b_debug then DLOG("fakedsplit: resolved split pos: "..tostring(pos-1)) end
@@ -640,7 +834,14 @@ function fakedsplit(ctx, desync)
local seqovl=0
if desync.arg.seqovl and tonumber(desync.arg.seqovl)>0 then
seqovl = tonumber(desync.arg.seqovl)
pat = desync.arg.seqovl_pattern and blob(desync,desync.arg.seqovl_pattern) or "\x00"
pat="\x00"
if desync.arg.seqovl_pattern then
if desync.arg.optional and not blob_exist(desync, desync.arg.seqovl_pattern) then
DLOG("fakedsplit: blob '"..desync.arg.seqovl_pattern.."' not found. using zero pattern")
else
pat = blob(desync,desync.arg.seqovl_pattern)
end
end
part = pattern(pat,1,seqovl)..part
end
if b_debug then DLOG("fakedsplit: sending real part 1 : 0-"..(pos-2).." len="..#part.." seqovl="..seqovl.." : "..hexdump_dlog(part)) end
@@ -694,6 +895,7 @@ end
-- arg : seqovl=N . decrease seq number of the second segment by N and fill N bytes with pattern (default - all zero). N must be less than the split pos.
-- arg : seqovl_pattern=<blob> . override seqovl pattern
-- arg : blob=<blob> - use this data instead of desync.dis.payload
-- arg : optional - skip if blob is absent. use zero pattern if seqovl_pattern blob is absent
-- arg : nodrop - do not drop current dissect
function fakeddisorder(ctx, desync)
if not desync.dis.tcp then
@@ -701,7 +903,10 @@ function fakeddisorder(ctx, desync)
return
end
direction_cutoff_opposite(ctx, desync)
-- by default process only outgoing known payloads
if desync.arg.optional and desync.arg.blob and not blob_exist(desync, desync.arg.blob) then
DLOG("fakeddisorder: blob '"..desync.arg.blob.."' not found. skipped")
return
end
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
if #data>0 and direction_check(desync) and payload_check(desync) then
if replay_first(desync) then
@@ -709,7 +914,7 @@ function fakeddisorder(ctx, desync)
local pos = resolve_pos(data, desync.l7payload, spos)
if pos then
if pos == 1 then
DLOG("multidisorder: split pos resolved to 0. cannot split.")
DLOG("fakeddisorder: split pos resolved to 0. cannot split.")
else
if b_debug then DLOG("fakeddisorder: resolved split pos: "..tostring(pos-1)) end
@@ -738,7 +943,14 @@ function fakeddisorder(ctx, desync)
DLOG("fakeddisorder: seqovl cancelled because seqovl "..seqovl.." is not less than the split pos "..(pos-1))
seqovl = 0
else
local pat = desync.arg.seqovl_pattern and blob(desync,desync.arg.seqovl_pattern) or "\x00"
local pat="\x00"
if desync.arg.seqovl_pattern then
if desync.arg.optional and not blob_exist(desync, desync.arg.seqovl_pattern) then
DLOG("fakeddisorder: blob '"..desync.arg.seqovl_pattern.."' not found. using zero pattern")
else
pat = blob(desync,desync.arg.seqovl_pattern)
end
end
part = pattern(pat,1,seqovl)..part
end
else
@@ -795,6 +1007,7 @@ end
-- arg : seqovl=N . decrease seq number of the first segment by N and fill N bytes with pattern (default - all zero)
-- arg : seqovl_pattern=<blob> . override pattern
-- arg : blob=<blob> - use this data instead of desync.dis.payload
-- arg : optional - skip if blob is absent. use zero pattern if seqovl_pattern blob is absent
function tcpseg(ctx, desync)
if not desync.dis.tcp then
instance_cutoff_shim(ctx, desync)
@@ -804,7 +1017,10 @@ function tcpseg(ctx, desync)
if not desync.arg.pos then
error("tcpseg: no pos specified")
end
-- by default process only outgoing known payloads
if desync.arg.optional and desync.arg.blob and not blob_exist(desync, desync.arg.blob) then
DLOG("tcpseg: blob '"..desync.arg.blob.."' not found. skipped")
return
end
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
if #data>0 and direction_check(desync) and payload_check(desync) then
if replay_first(desync) then
@@ -818,7 +1034,14 @@ function tcpseg(ctx, desync)
local seqovl=0
if desync.arg.seqovl and tonumber(desync.arg.seqovl)>0 then
seqovl = tonumber(desync.arg.seqovl)
local pat = desync.arg.seqovl_pattern and blob(desync,desync.arg.seqovl_pattern) or "\x00"
local pat="\x00"
if desync.arg.seqovl_pattern then
if desync.arg.optional and not blob_exist(desync, desync.arg.seqovl_pattern) then
DLOG("tcpseg: blob '"..desync.arg.seqovl_pattern.."' not found. using zero pattern")
else
pat = blob(desync,desync.arg.seqovl_pattern)
end
end
part = pattern(pat,1,seqovl)..part
end
if b_debug then DLOG("tcpseg: sending "..(pos[1]-1).."-"..(pos[2]-1).." len="..#part.." seqovl="..seqovl.." : "..hexdump_dlog(part)) end
@@ -874,7 +1097,7 @@ end
-- nfqws1 : "--dpi-desync=tamper" for dht proto
-- standard args : direction
-- arg : dn=N - message starts from "dN". 2 by default
-- arg : dn=N - message starts from "dN". 3 by default
function dht_dn(ctx, desync)
if not desync.dis.udp then
instance_cutoff_shim(ctx, desync)
@@ -882,7 +1105,7 @@ function dht_dn(ctx, desync)
end
direction_cutoff_opposite(ctx, desync)
if desync.l7payload=="dht" and direction_check(desync) then
local N = tonumber(desync.arg.dn) or 2
local N = tonumber(desync.arg.dn) or 3
-- remove "d1" from the start not breaking bencode
local prefix = "d"..tostring(N)..":"..string.rep("0",N).."1:x"
desync.dis.payload = prefix..string.sub(desync.dis.payload,2)

View File

@@ -1,24 +1,62 @@
-- standard automation/orchestration code
-- this is related to making dynamic strategy decisions without rewriting or altering strategy function code
-- orchestrators can decide which instances to call or not to call or pass them dynamic arguments
-- failure and success detectors test potential block conditions for orchestrators
-- standard host key generator for per-host storage
-- arg: reqhost - require hostname, do not work with ip
function automate_host_record(desync)
local key
if desync.arg.reqhost then
key = desync.track and desync.track.hostname
else
key = host_or_ip(desync)
-- arg: nld=N - cut hostname to N level domain. NLD=2 static.intranet.microsoft.com => microsoft.com
function standard_hostkey(desync)
local hostkey = desync.track and desync.track.hostname
if hostkey then
if desync.arg.nld and tonumber(desync.arg.nld)>0 and not (desync.track and desync.track.hostname_is_ip) then
-- dissect_nld returns nil if domain is invalid or does not have this NLD
-- fall back to original hostkey if it fails
local hktemp = dissect_nld(hostkey, tonumber(desync.arg.nld))
if hktemp then
hostkey = hktemp
end
end
elseif not desync.arg.reqhost then
hostkey = host_ip(desync)
end
if not key then
return hostkey
end
-- per-host storage
-- arg: key - a string - table name inside autostate table. to allow multiple orchestrator instances to use single host storage
-- arg: hostkey - hostkey generator function name
function automate_host_record(desync)
local hostkey, hkf, askey
if desync.arg.hostkey then
if type(_G[desync.arg.hostkey])~="function" then
error("automate: invalid hostkey function '"..desync.arg.hostkey.."'")
end
hkf = _G[desync.arg.hostkey]
else
hkf = standard_hostkey
end
hostkey = hkf(desync)
if not hostkey then
DLOG("automate: host record key unavailable")
return nil
end
DLOG("automate: host record key '"..key.."'")
askey = (desync.arg.key and #desync.arg.key>0) and desync.arg.key or desync.func_instance
DLOG("automate: host record key 'autostate."..askey.."."..hostkey.."'")
if not autostate then
autostate = {}
end
if not autostate[key] then
autostate[key] = {}
if not autostate[askey] then
autostate[askey] = {}
end
return autostate[key]
if not autostate[askey][hostkey] then
autostate[askey][hostkey] = {}
end
return autostate[askey][hostkey]
end
-- per-connection storage
function automate_conn_record(desync)
if not desync.track.lua_state.automate then
desync.track.lua_state.automate = {}
@@ -56,6 +94,13 @@ function automate_failure_counter(hrec, crec, fails, maxtime)
end
return false
end
-- resets failure counter if it has started counting
function automate_failure_counter_reset(hrec)
if hrec.failure_counter then
DLOG("automate: failure counter reset")
hrec.failure_counter = nil
end
end
-- location is url compatible with Location: header
-- hostname is original hostname
@@ -69,24 +114,203 @@ function is_dpi_redirect(hostname, location)
return false
end
function standard_detector_defaults(arg)
return {
inseq = tonumber(arg.inseq) or 4096,
retrans = tonumber(arg.retrans) or 3,
maxseq = tonumber(arg.maxseq) or 32768,
udp_in = tonumber(arg.udp_in) or 1,
udp_out = tonumber(arg.udp_out) or 4,
no_http_redirect = arg.no_http_redirect,
no_rst = arg.no_rst,
reset = arg.reset
}
end
-- standard failure detector
-- works with tcp and udp
-- detected failures:
-- incoming RST
-- incoming http redirection
-- outgoing retransmissions
-- udp too much out with too few in
-- arg: maxseq=<rseq> - tcp: test retransmissions only within this relative sequence. default is 32K
-- arg: retrans=N - tcp: retrans count threshold. default is 3
-- arg: reset - send RST to retransmitter to break long wait
-- arg: inseq=<rseq> - tcp: maximum relative sequence number to treat incoming RST as DPI reset. default is 4K
-- arg: no_http_redirect - tcp: disable http_reply dpi redirect trigger
-- arg: no_rst - tcp: disable incoming RST trigger
-- arg: udp_out - udp: >= outgoing udp packets. default is 4
-- arg: udp_in - udp: with <= incoming udp packets. default is 1
function standard_failure_detector(desync, crec)
local arg = standard_detector_defaults(desync.arg)
local trigger = false
if desync.dis.tcp then
local seq = pos_get(desync,'s')
if desync.outgoing then
if #desync.dis.payload>0 and arg.retrans and arg.maxseq>0 and seq<=arg.maxseq and (crec.retrans or 0)<arg.retrans then
if is_retransmission(desync) then
crec.retrans = crec.retrans and (crec.retrans+1) or 1
DLOG("standard_failure_detector: retransmission "..crec.retrans.."/"..arg.retrans)
trigger = crec.retrans>=arg.retrans
if trigger and arg.reset then
local dis = deepcopy(desync.dis)
dis.payload = nil
dis_reverse(dis)
dis.tcp.th_flags = TH_RST
dis.tcp.th_win = desync.track and desync.track.pos.reverse.tcp.winsize or 64
dis.tcp.options = nil
if dis.ip6 then
dis.ip6.ip6_flow = (desync.track and desync.track.pos.reverse.ip6_flow) and desync.track.pos.reverse.ip6_flow or 0x60000000;
end
DLOG("standard_failure_detector: sending RST to retransmitter")
rawsend_dissect(dis, {ifout = desync.ifin})
end
end
end
else
if not arg.no_rst and arg.inseq>0 and bitand(desync.dis.tcp.th_flags, TH_RST)~=0 and seq>=1 then
trigger = seq<=arg.inseq
if b_debug then
if trigger then
DLOG("standard_failure_detector: incoming RST s"..seq.." in range s"..arg.inseq)
else
DLOG("standard_failure_detector: not counting incoming RST s"..seq.." beyond s"..arg.inseq)
end
end
elseif not arg.no_http_redirect and desync.l7payload=="http_reply" and desync.track.hostname then
local hdis = http_dissect_reply(desync.dis.payload)
if hdis and (hdis.code==302 or hdis.code==307) and hdis.headers.location and hdis.headers.location then
trigger = is_dpi_redirect(desync.track.hostname, hdis.headers.location.value)
if b_debug then
if trigger then
DLOG("standard_failure_detector: http redirect "..hdis.code.." to '"..hdis.headers.location.value.."'. looks like DPI redirect.")
else
DLOG("standard_failure_detector: http redirect "..hdis.code.." to '"..hdis.headers.location.value.."'. NOT a DPI redirect.")
end
end
end
end
end
elseif desync.dis.udp then
if desync.outgoing then
if arg.udp_out>0 then
local pos_out = pos_get(desync,'n',false)
local pos_in = pos_get(desync,'n',true)
trigger = pos_out>=arg.udp_out and pos_in<=arg.udp_in
if trigger then
if b_debug then
DLOG("standard_failure_detector: arg.udp_out "..pos_out..">="..arg.udp_out.." arg.udp_in "..pos_in.."<="..arg.udp_in)
end
end
end
end
end
return trigger
end
-- standard success detector
-- success means previous failures were temporary and counter should be reset
-- detected successes:
-- tcp: outgoing seq is beyond 'maxseq' and maxseq>0
-- tcp: incoming seq is beyond 'inseq' and inseq>0
-- udp: incoming packets count > `udp_in` and `udp_out`>0
-- arg: maxseq=<rseq> - tcp: success if outgoing relative sequence is beyond this value. default is 32K
-- arg: inseq=<rseq> - tcp: success if incoming relative sequence is beyond this value. default is 4K
-- arg: udp_out - udp : must be nil or >0 to test udp_in
-- arg: udp_in - udp: if number if incoming packets > udp_in it means success
function standard_success_detector(desync, crec)
local arg = standard_detector_defaults(desync.arg)
if desync.dis.tcp then
local seq = pos_get(desync,'s')
if desync.outgoing then
if arg.maxseq>0 and seq>arg.maxseq then
DLOG("standard_success_detector: outgoing s"..seq.." is beyond s"..arg.maxseq..". treating connection as successful")
return true
end
else
if arg.inseq>0 and seq>arg.inseq then
DLOG("standard_success_detector: incoming s"..seq.." is beyond s"..arg.inseq..". treating connection as successful")
return true
end
end
elseif desync.dis.udp then
if not desync.outgoing then
local pos = pos_get(desync,'n')
if arg.udp_out>0 and pos>arg.udp_in then
if b_debug then
DLOG("standard_success_detector: arg.udp_in "..pos..">"..arg.udp_in)
end
return true
end
end
end
return false
end
-- calls success and failure detectors
-- resets counter if success is detected
-- increases counter if failure is detected
-- returns true if failure counter exceeds threshold
function automate_failure_check(desync, hrec, crec)
if crec.nocheck then return false end
local failure_detector, success_detector
if desync.arg.failure_detector then
if type(_G[desync.arg.failure_detector])~="function" then
error("automate: invalid failure detector function '"..desync.arg.failure_detector.."'")
end
failure_detector = _G[desync.arg.failure_detector]
else
failure_detector = standard_failure_detector
end
if desync.arg.success_detector then
if type(_G[desync.arg.success_detector])~="function" then
error("automate: invalid success detector function '"..desync.arg.success_detector.."'")
end
success_detector = _G[desync.arg.success_detector]
else
success_detector = standard_success_detector
end
if success_detector(desync, crec) then
crec.nocheck = true
DLOG("automate: success detected")
automate_failure_counter_reset(hrec)
return false
end
if failure_detector(desync, crec) then
crec.nocheck = true
DLOG("automate: failure detected")
local fails = tonumber(desync.arg.fails) or 3
local maxtime = tonumber(desync.arg.time) or 60
return automate_failure_counter(hrec, crec, fails, maxtime)
end
return false
end
-- circularily change strategy numbers when failure count reaches threshold ('fails')
-- detected failures: incoming RST, incoming http redirection, outgoing retransmissions
-- this orchestrator requires redirection of incoming traffic to cache RST and http replies !
-- each orchestrated instance must have strategy=N arg, where N starts from 1 and increment without gaps
-- if 'final' arg is present in an orchestrated instance it stops rotation
-- arg: fails=N - failture count threshold. default is 3
-- arg: retrans=N - retrans count threshold. default is 3
-- arg: seq=<rseq> - if packet is beyond this relative sequence number treat this connection as successful. default is 64K
-- arg: rst=<rseq> - maximum relative sequence number to treat incoming RST as DPI reset. default is 1
-- arg: time=<sec> - if last failure happened earlier than `maxtime` seconds ago - reset failure counter. default is 60.
-- arg: reqhost - pass with no tampering if hostname is unavailable
-- test case: nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-auto.lua --in-range=-s1 --lua-desync=circular --lua-desync=argdebug:strategy=1 --lua-desync=argdebug:strategy=2
-- arg: success_detector - success detector function name
-- arg: failure_detector - failure detector function name
-- arg: hostkey - hostkey generator function name
-- args for failure detector - see standard_failure_detector or your own detector
-- args for success detector - see standard_success_detector or your own detector
-- args for hostkey generator - see standard_hostkey or your own generator
-- test case: --in-range=-s34228 --lua-desync=circular --lua-desync=argdebug:strategy=1 --lua-desync=argdebug:strategy=2
function circular(ctx, desync)
local function count_strategies(hrec, plan)
local function count_strategies(hrec)
if not hrec.ctstrategy then
local uniq={}
local n=0
for i,instance in pairs(plan) do
for i,instance in pairs(desync.plan) do
if instance.arg.strategy then
n = tonumber(instance.arg.strategy)
if not n or n<1 then
@@ -109,122 +333,170 @@ function circular(ctx, desync)
end
end
-- take over orchestration. prevent further instance execution in case of error
execution_plan_cancel(ctx)
-- take over execution. prevent further instance execution in case of error
orchestrate(ctx, desync)
if not desync.dis.tcp then
DLOG("circular: this orchestrator is tcp only")
instance_cutoff(ctx)
return
end
if not desync.track then
DLOG_ERR("circular: conntrack is missing but required")
return
end
local plan = execution_plan(ctx)
if #plan==0 then
DLOG("circular: need some desync instances or useless")
return
end
local hrec = automate_host_record(desync)
if not hrec then
DLOG("circular: passing with no tampering")
return
end
count_strategies(hrec, plan)
count_strategies(hrec)
if hrec.ctstrategy==0 then
error("circular: add strategy=N tag argument to each following instance ! N must start from 1 and increment")
end
local rstseq = tonumber(desync.arg.rst) or 1
local maxseq = tonumber(desync.arg.seq) or 0x10000
local fails = tonumber(desync.arg.fails) or 3
local retrans = tonumber(desync.arg.retrans) or 3
local maxtime = tonumber(desync.arg.time) or 60
local crec = automate_conn_record(desync)
local pos = bitand(desync.track.tcp.seq - desync.track.tcp.seq0,0xFFFFFFFF)
local trigger = false
if not hrec.nstrategy then
DLOG("circular: start from strategy 1")
hrec.nstrategy = 1
end
if not crec.nocheck then
local seq = pos_get(desync,'s')
if seq>maxseq then
DLOG("circular: s"..seq.." is beyond s"..maxseq..". treating connection as successful")
crec.nocheck = true
end
end
local verdict = VERDICT_PASS
if not crec.nocheck and hrec.final~=hrec.nstrategy then
if desync.outgoing then
if #desync.dis.payload>0 and (crec.retrans or 0)<retrans then
if not crec.uppos then crec.uppos=0 end
if desync.track.tcp.pos_orig<=crec.uppos then
crec.retrans = crec.retrans and (crec.retrans+1) or 1
DLOG("circular: retransmission "..crec.retrans.."/"..retrans)
trigger = crec.retrans>=retrans
end
if desync.track.tcp.pos_orig>crec.uppos then
crec.uppos=desync.track.tcp.pos_orig
end
end
else
if bitand(desync.dis.tcp.th_flags, TH_RST)~=0 then
local seq=u32add(desync.track.tcp.ack, -desync.track.tcp.ack0)
trigger = seq<=rstseq
if b_debug then
if trigger then
DLOG("circular: incoming RST s"..seq.." in range s"..rstseq)
else
DLOG("circular: not counting incoming RST s"..seq.." beyond s"..rstseq)
end
end
elseif desync.l7payload=="http_reply" and desync.track.hostname then
local hdis = http_dissect_reply(desync.dis.payload)
if hdis and (hdis.code==302 or hdis.code==307) and hdis.headers.location and hdis.headers.location then
trigger = is_dpi_redirect(desync.track.hostname, hdis.headers.location.value)
if trigger and b_debug then
DLOG("circular: http redirect "..hdis.code.." to '"..hdis.headers.location.value.."'")
end
end
end
end
if trigger then
if automate_failure_counter(hrec, crec, fails, maxtime) then
-- circular strategy change
hrec.nstrategy = (hrec.nstrategy % hrec.ctstrategy) + 1
DLOG("circular: rotate strategy to "..hrec.nstrategy)
if hrec.nstrategy == hrec.final then
DLOG("circular: final strategy "..hrec.final.." reached. will rotate no more.")
end
if hrec.final~=hrec.nstrategy then
local crec = automate_conn_record(desync)
if automate_failure_check(desync, hrec, crec) then
hrec.nstrategy = (hrec.nstrategy % hrec.ctstrategy) + 1
DLOG("circular: rotate strategy to "..hrec.nstrategy)
if hrec.nstrategy == hrec.final then
DLOG("circular: final strategy "..hrec.final.." reached. will rotate no more.")
end
end
end
DLOG("circular: current strategy "..hrec.nstrategy)
local dcopy = desync_copy(desync)
for i=1,#plan do
if plan[i].arg.strategy and tonumber(plan[i].arg.strategy)==hrec.nstrategy then
apply_execution_plan(dcopy, plan[i])
if cutoff_shim_check(dcopy) then
DLOG("circular: not calling '"..dcopy.func_instance.."' because of voluntary cutoff")
elseif not payload_match_filter(dcopy.l7payload, plan[i].payload_filter) then
DLOG("circular: not calling '"..dcopy.func_instance.."' because payload '"..dcopy.l7payload.."' does not match filter '"..plan[i].payload_filter.."'")
elseif not pos_check_range(dcopy, plan[i].range) then
DLOG("circular: not calling '"..dcopy.func_instance.."' because pos "..pos_str(dcopy,plan[i].range.from).." "..pos_str(dcopy,plan[i].range.to).." is out of range '"..pos_range_str(plan[i].range).."'")
else
DLOG("circular: calling '"..dcopy.func_instance.."'")
verdict = verdict_aggregate(verdict,_G[plan[i].func](nil, dcopy))
end
while true do
local instance = plan_instance_pop(desync)
if not instance then break end
if instance.arg.strategy and tonumber(instance.arg.strategy)==hrec.nstrategy then
verdict = plan_instance_execute(desync, verdict, instance)
end
end
return verdict
end
-- test iff functions
function cond_true(desync)
return true
end
function cond_false(desync)
return false
end
-- arg: percent - of true . 50 by default
function cond_random(desync)
return math.random(0,99)<(tonumber(desync.arg.percent) or 50)
end
-- this iif function detects packets having 'arg.pattern' string in their payload
-- test case : --lua-desync=condition:iff=cond_payload_str:pattern=1234 --lua-desync=argdebug:testarg=1 --lua-desync=argdebug:testarg=2:morearg=xyz
-- test case (true) : echo aaz1234zzz | ncat -4u 1.1.1.1 443
-- test case (false) : echo aaze124zzz | ncat -4u 1.1.1.1 443
function cond_payload_str(desync)
if not desync.arg.pattern then
error("cond_payload_str: missing 'pattern'")
end
return string.find(desync.dis.payload,desync.arg.pattern,1,true)
end
-- check iff function available. error if not
function require_iff(desync, name)
if not desync.arg.iff then
error(name..": missing 'iff' function")
end
if type(_G[desync.arg.iff])~="function" then
error(name..": invalid 'iff' function '"..desync.arg.iff.."'")
end
end
-- execute further desync instances only if user-provided 'iff' function returns true
-- for example, this can be used by custom protocol detectors
-- arg: iff - condition function. takes desync as arg and returns bool. (cant use 'if' because of reserved word)
-- arg: neg - invert condition function result
-- test case : --lua-desync=condition:iff=cond_random --lua-desync=argdebug:testarg=1 --lua-desync=argdebug:testarg=2:morearg=xyz
function condition(ctx, desync)
require_iff(desync, "condition")
orchestrate(ctx, desync)
if logical_xor(_G[desync.arg.iff](desync), desync.arg.neg) then
DLOG("condition: true")
return replay_execution_plan(desync)
else
DLOG("condition: false")
plan_clear(desync)
end
end
-- clear execution plan if user provided 'iff' functions returns true
-- can be used with other orchestrators to stop execution conditionally
-- arg: iff - condition function. takes desync as arg and returns bool. (cant use 'if' because of reserved word)
-- arg: neg - invert condition function result
-- test case : --in-range=-s1 --lua-desync=circular --lua-desync=stopif:iff=cond_random:strategy=1 --lua-desync=argdebug:strategy=1 --lua-desync=argdebug:strategy=2
function stopif(ctx, desync)
require_iff(desync, "stopif")
orchestrate(ctx, desync)
if logical_xor(_G[desync.arg.iff](desync), desync.arg.neg) then
DLOG("stopif: true")
plan_clear(desync)
else
-- do not do anything. allow other orchestrator to finish the plan
DLOG("stopif: false")
end
end
-- repeat following 'instances' 'repeats' times, execute others with no tampering
-- arg: instances - number of following instances to be repeated. 1 by default
-- arg: repeats - number of repeats
-- arg: iff - condition function to continue execution. takes desync as arg and returns bool. (cant use 'if' because of reserved word)
-- arg: neg - invert condition function result
-- arg: stop - do not replay remaining execution plan after 'instances'
-- arg: clear - clear execution plan after 'instances'
-- test case : --lua-desync=repeater:repeats=2:instances=2 --lua-desync=argdebug:v=1 --lua-desync=argdebug:v=2 --lua-desync=argdebug:v=3
function repeater(ctx, desync)
local repeats = tonumber(desync.arg.repeats)
if not repeats then
error("repeat: missing 'repeats'")
end
local iff = desync.arg.iff or "cond_true"
if type(_G[iff])~="function" then
error(name..": invalid 'iff' function '"..iff.."'")
end
orchestrate(ctx, desync)
local neg = desync.arg.neg
local stop = desync.arg.stop
local clear = desync.arg.clear
local verdict = VERDICT_PASS
local instances = tonumber(desync.arg.instances) or 1
local repinst = desync.func_instance
if instances>#desync.plan then
instances = #desync.plan
end
-- save plan copy
local plancopy = deepcopy(desync.plan)
for r=1,repeats do
if not logical_xor(_G[iff](desync), neg) then
DLOG("repeater: break by iff")
break
end
DLOG("repeater: "..repinst.." "..r.."/"..repeats)
-- nested orchestrators can also pop
local ct_end = #desync.plan - instances
repeat
local instance = plan_instance_pop(desync)
verdict = plan_instance_execute(desync, verdict, instance)
until #desync.plan <= ct_end
-- rollback desync plan
desync.plan = deepcopy(plancopy)
end
-- remove repeated instances from desync plan
for i=1,instances do
table.remove(desync.plan,1)
end
if clear then
plan_clear(desync)
return verdict
elseif stop then
return verdict
end
-- replay the rest
return verdict_aggregate(verdict, replay_execution_plan(desync))
end

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,6 @@ function pcap_write_packet(file, raw)
local sec, nsec = clock_gettime();
file:write(bu32(sec)..bu32(nsec)..bu32(#raw)..bu32(#raw))
file:write(raw)
file:close()
end
function pcap_write(file, raw)
local pos = file:seek()
@@ -16,7 +15,7 @@ function pcap_write(file, raw)
pcap_write_packet(file, raw)
end
-- test case : nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-pcap.lua --writeable=zdir --in-range=a --lua-desync=pcap:file=test.pcap
-- test case : --writeable=zdir --in-range=a --lua-desync=pcap:file=test.pcap
-- arg : file=<filename> - file for storing pcap data. if --writeable is specified and filename is relative - append filename to writeable path
-- arg : keep - do not overwrite file, append packets to existing
function pcap(ctx, desync)
@@ -36,4 +35,5 @@ function pcap(ctx, desync)
error("pcap: could not write to '".._G[fn_cache_name].."'")
end
pcap_write(f, raw_packet(ctx))
f:close()
end

View File

@@ -13,7 +13,7 @@ end
function test_all(...)
test_run({test_crypto, test_bin, test_ipstr, test_dissect, test_csum, test_resolve, test_rawsend},...)
test_run({test_crypto, test_bin, test_gzip, test_ipstr, test_dissect, test_csum, test_resolve, test_rawsend},...)
end
@@ -251,12 +251,12 @@ function test_aes_ctr()
end
function test_ub()
for k,f in pairs({{u8,bu8,0xFF,8}, {u16,bu16,0xFFFF,16}, {u24,bu24,0xFFFFFF,24}, {u32,bu32,0xFFFFFFFF,32}}) do
for k,f in pairs({{u8,bu8,0xFF,8}, {u16,bu16,0xFFFF,16}, {u24,bu24,0xFFFFFF,24}, {u32,bu32,0xFFFFFFFF,32}, {u48,bu48,0xFFFFFFFFFFFF,48}}) do
local v = math.random(0,f[3])
local pos = math.random(1,20)
local s = brandom(pos-1)..f[2](v)..brandom(20)
local v2 = f[1](s,pos)
print("u"..tostring(f[4]).." pos="..tostring(pos).." "..tostring(v).." "..tostring(v2))
print(string.format("u%u pos=%u %016X %016X",f[4],pos,v,v2))
test_assert(v==v2)
end
end
@@ -264,38 +264,76 @@ end
function test_bit()
local v, v2, v3, v4, b1, b2, pow
v = math.random(0,0xFFFFFFFF)
b1 = math.random(1,16)
for i=1,100 do
v = math.random(0,0xFFFFFFFFFFFF)
b1 = math.random(1,16)
v2 = bitrshift(v, b1)
pow = 2^b1
v3 = divint(v, pow)
print(string.format("rshift(0x%X,%u) = 0x%X 0x%X/%u = 0x%X", v,b1,v2, v,pow,v3))
v2 = bitrshift(v, b1)
pow = 2^b1
v3 = divint(v, pow)
print(string.format("rshift(0x%X,%u) = 0x%X 0x%X/%u = 0x%X", v,b1,v2, v,pow,v3))
test_assert(v2==v3)
v = math.random(0,0xFFFFFFFFF)
b1 = math.random(1,12)
v2 = bitlshift(v, b1)
pow = 2^b1
v3 = (v * pow) % 0x1000000000000
print(string.format("lshift(0x%X,%u) = 0x%X 0x%X*%u %% 0x100000000000 = 0x%X", v,b1,v2, v,pow,v3))
test_assert(v2==v3)
v2 = math.random(0,0xFFFFFFFFFFFF)
v3 = bitxor(v, v2)
v4 = bitor(v, v2) - bitand(v, v2)
print(string.format("xor(0x%X,0x%X) = %X or/and/minus = %X", v, v2, v3, v4))
test_assert(v3==v4)
b1 = math.random(1,31)
b2 = b1 + math.random(1,16)
v2 = bitget(v, b1, b2)
pow = 2^(b2-b1+1) - 1
v3 = bitand(bitrshift(v,b1), pow)
print(string.format("bitget(0x%X,%u,%u) = 0x%X bitand/bitrshift/pow = 0x%X", v, b1, b2, v2, v3))
test_assert(v2==v3)
v4 = math.random(0,pow)
v2 = bitset(v, b1, b2, v4)
v3 = bitor(bitlshift(v4, b1), bitand(v, bitnot(bitlshift(pow, b1))))
print(string.format("bitset(0x%X,%u,%u,0x%X) = 0x%X bitand/bitnot/bitlshift/pow = 0x%X", v, b1, b2, v4, v2, v3))
test_assert(v2==v3)
end
end
function test_swap()
local v1, v2, v3
v1 = math.random(0,0xFFFF)
v2 = swap16(v1)
v3 = divint(v1,0x100) + v1%0x100*0x100
print("swap16: "..(v2==v3 and "OK" or "FAIL"))
test_assert(v2==v3)
v2 = bitlshift(v, b1)
pow = 2^b1
v3 = (v * pow) % 0x100000000
print(string.format("lshift(0x%X,%u) = 0x%X 0x%X*%u %% 0x10000000 = 0x%X", v,b1,v2, v,pow,v3))
v1 = math.random(0,0xFFFFFF)
v2 = swap24(v1)
v3 = divint(v1,0x10000) + divint(v1,0x100)%0x100*0x100 + v1%0x100*0x10000
print("swap24: "..(v2==v3 and "OK" or "FAIL"))
test_assert(v2==v3)
v2 = math.random(0,0xFFFFFFFF)
v3 = bitxor(v, v2)
v4 = bitor(v, v2) - bitand(v, v2)
print(string.format("xor(0x%X,0x%X) = %X or/and/minus = %X", v, v2, v3, v4))
test_assert(v3==v4)
b2 = b1 + math.random(1,15)
v2 = bitget(v, b1, b2)
pow = 2^(b2-b1+1) - 1
v3 = bitand(bitrshift(v,b1), pow)
print(string.format("bitget(0x%X,%u,%u) = 0x%X bitand/bitrshift/pow = 0x%X", v, b1, b2, v2, v3))
v1 = math.random(0,0xFFFFFFFF)
v2 = swap32(v1)
v3 = divint(v1,0x1000000) + divint(v1,0x10000)%0x100*0x100 + divint(v1,0x100)%0x100*0x10000 + v1%0x100*0x1000000
print("swap32: "..(v2==v3 and "OK" or "FAIL"))
test_assert(v2==v3)
v4 = math.random(0,pow)
v2 = bitset(v, b1, b2, v4)
v3 = bitor(bitlshift(v4, b1), bitand(v, bitnot(bitlshift(pow, b1))))
print(string.format("bitset(0x%X,%u,%u,0x%X) = 0x%X bitand/bitnot/bitlshift/pow = 0x%X", v, b1, b2, v4, v2, v3))
v1 = math.random(0,0xFFFFFFFFFFFF)
v2 = swap48(v1)
v3 = divint(v1,0x10000000000) +
divint(v1,0x100000000)%0x100*0x100 +
divint(v1,0x1000000)%0x100*0x10000 +
divint(v1,0x10000)%0x100*0x1000000 +
divint(v1,0x100)%0x100*0x100000000 +
v1%0x100*0x10000000000
print("swap48: "..(v2==v3 and "OK" or "FAIL"))
test_assert(v2==v3)
end
@@ -305,7 +343,8 @@ function test_ux()
{ add=u8add, fname="u8add", max = 0xFF },
{ add=u16add, fname="u16add", max = 0xFFFF },
{ add=u24add, fname="u24add", max = 0xFFFFFF },
{ add=u32add, fname="u32add", max = 0xFFFFFFFF }
{ add=u32add, fname="u32add", max = 0xFFFFFFFF },
{ add=u48add, fname="u48add", max = 0xFFFFFFFFFFFF }
}) do
io.write(test.fname.." : ")
for i=1,1000 do
@@ -315,7 +354,7 @@ function test_ux()
usum = test.add(v1,v2,v3)
sum = bitand((v1+v2+v3)%(test.max+1),test.max)
if sum~=usum then
print("FAIL")
print(string.format("FAIL: 0x%012X + 0x%012X + 0x%012X = 0x%012X 0x%012X",v1,v2,v3,usum,sum))
end
test_assert(sum==usum)
end
@@ -324,9 +363,38 @@ function test_ux()
end
function test_bin(...)
test_run({test_ub, test_bit, test_ux},...)
test_run({test_ub, test_bit, test_swap, test_ux},...)
end
function test_gzip()
local s=""
for i=1,math.random(2000,3000) do
local rnd=brandom(math.random(1,50))
s=s..rnd..string.rep(bu8(math.random(0,255)),100-#rnd)
end
local v=math.random(100001,199999)
local level=math.random(1,9)
local memlevel=math.random(1,8)
print("gzip: original size "..#s)
print("gzip: cut point "..(v+1))
print("gzip: level "..level)
print("gzip: memlevel "..memlevel)
local gz = gzip_init(nil, level, memlevel)
local zip = gzip_deflate(gz,string.sub(s,1,v))
zip = zip..gzip_deflate(gz,string.sub(s,v+1))
zip = zip..gzip_deflate(gz,nil) -- finalize
gzip_end(gz)
print("gzip: deflated size "..#zip)
local v=math.random(2,#zip-1)
print("gunzip: cut point "..(v+1))
gz = gunzip_init()
local unzip = gunzip_inflate(gz,string.sub(zip,1,v))
unzip = unzip..gunzip_inflate(gz,string.sub(zip,v+1))
gunzip_end(gz)
print("gunzip: inflated size "..#unzip)
print("gzip+gunzip: "..(s==unzip and "OK" or "FAIL"))
test_assert(s==unzip)
end
function test_ipstr()
local s_ip, ip, s_ip2
@@ -564,25 +632,50 @@ end
function test_resolve()
local pos
pos = zero_based_pos(resolve_multi_pos(fake_default_tls,"tls_client_hello","1,extlen,sniext,host,sld,midsld,endsld,endhost,-5"))
local tdis = tls_dissect(fake_default_tls)
local extlen_pos = 5 + 6 + 32 + 1 + 2 + 1 + #tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.session_id + #tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.cipher_suites*2 + #tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.compression_methods
print("fake_default_tls size "..#fake_default_tls.." extlen="..extlen_pos)
local m="1,extlen,sniext,host,sld,midsld,endsld,endhost,-5"
pos = resolve_multi_pos(fake_default_tls,"tls_client_hello",m,true)
test_assert(pos)
print("resolve_multi_pos tls : "..table.concat(pos," "))
pos = zero_based_pos(resolve_range(fake_default_tls,"tls_client_hello","host,endhost"))
print("resolve_multi_pos tls : "..m.." : "..table.concat(pos," "))
m = "host,endhost"
pos = resolve_range(fake_default_tls,"tls_client_hello",m,false,true)
test_assert(pos)
print("resolve_range tls : "..table.concat(pos," "))
pos = resolve_pos(fake_default_tls,"tls_client_hello","midsld")
print("resolve_range tls : "..m.." : "..table.concat(pos," "))
m = "1"
pos = resolve_pos(fake_default_tls,"tls_client_hello",m,true)
test_assert(pos==1)
print("resolve_pos tls : "..m.." : "..pos)
m = "-1"
pos = resolve_pos(fake_default_tls,"tls_client_hello",m,true)
test_assert(pos==(#fake_default_tls-1))
print("resolve_pos tls : "..m.." : "..pos)
m = "extlen"
pos = resolve_pos(fake_default_tls,"tls_client_hello",m,true)
test_assert(pos==extlen_pos)
print("resolve_pos tls : "..m.." : "..pos)
m = "midsld"
pos = resolve_pos(fake_default_tls,"tls_client_hello",m,true)
test_assert(pos)
print("resolve_pos tls : "..pos - 1)
pos = resolve_pos(fake_default_tls,"tls_client_hello","method")
print("resolve_pos tls : "..m.." : "..pos)
m = "method"
pos = resolve_pos(fake_default_tls,"tls_client_hello",m,true)
test_assert(not pos)
print("resolve_pos tls non-existent : "..tostring(pos))
print("resolve_pos tls non-existent : "..m.." : "..tostring(pos))
pos = zero_based_pos(resolve_multi_pos(fake_default_http,"http_req","method,host,sld,midsld,endsld,endhost,-5"))
local host_pos = string.find(fake_default_http,"Host: ")+6-1
print("fake_default_http size "..#fake_default_http.." host="..host_pos)
m = "method,host,sld,midsld,endsld,endhost,-5"
pos = resolve_multi_pos(fake_default_http,"http_req",m,true)
test_assert(pos)
print("resolve_multi_pos http : "..table.concat(pos," "))
pos = resolve_pos(fake_default_http,"http_req","sniext")
test_assert(pos[1]==0)
test_assert(pos[2]==host_pos)
print("resolve_multi_pos http : "..m.." : "..table.concat(pos," "))
m = "sniext"
pos = resolve_pos(fake_default_http,"http_req",m,true)
test_assert(not pos)
print("resolve_pos http non-existent : "..tostring(pos))
print("resolve_pos http non-existent : "..m.." : "..tostring(pos))
end
function test_rawsend(opts)

View File

@@ -1,4 +1,4 @@
-- test case : nfqws2 --qnum 200 --debug --lua-init=@zapret-wgobfs.lua --in-range=a --out-range=a --lua-desync=wgobfs:secret=mycoolpassword
-- test case : --in-range=a --out-range=a --lua-desync=wgobfs:secret=mycoolpassword
-- encrypt standard wireguard messages - initiation, response, cookie - and change udp packet size
-- do not encrypt data messages and keepalives
-- wgobfs adds maximum of 30+padmax bytes to udp size

View File

@@ -30,7 +30,8 @@
#endif
#include <time.h>
#define RESOLVER_EAGAIN_ATTEMPTS 2
#define RESOLVER_EAGAIN_ATTEMPTS 10
#define RESOLVER_EAGAIN_DELAY 500
static void trimstr(char *s)
{
@@ -87,7 +88,7 @@ static bool dom_valid(char *dom)
static void invalid_domain_beautify(char *dom)
{
for (int i = 0; *dom && i < 64; i++, dom++)
if (*dom < 0x20 || *dom>0x7F) *dom = '?';
if (*dom < 0x20 || *dom<0) *dom = '?';
if (*dom) *dom = 0;
}
@@ -97,7 +98,7 @@ static struct
{
char verbose;
char family;
int threads;
int threads, eagain, eagain_delay;
time_t start_time;
pthread_mutex_t flock;
pthread_mutex_t slock; // stats lock
@@ -193,11 +194,12 @@ static void *t_resolver(void *arg)
int i, r;
char dom[256];
bool is_ok;
struct addrinfo hints;
struct addrinfo *result;
struct addrinfo hints, *result;
struct timespec ts_eagain = { .tv_sec = glob.eagain_delay/1000, .tv_nsec=glob.eagain_delay%1000*1000000 };
VLOG("started");
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = (glob.family == FAMILY4) ? AF_INET : (glob.family == FAMILY6) ? AF_INET6 : AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
@@ -244,12 +246,16 @@ static void *t_resolver(void *arg)
else if (dom_valid(dom))
{
VLOG("resolving %s", dom);
for (i = 0; i < RESOLVER_EAGAIN_ATTEMPTS; i++)
for (i = 0; i < glob.eagain; i++)
{
if ((r = getaddrinfo(dom, NULL, &hints, &result)))
{
VLOG("failed to resolve %s : result %d (%s)", dom, r, eai_str(r));
if (r == EAI_AGAIN) continue; // temporary failure. should retry
if (r == EAI_AGAIN)
{
nanosleep(&ts_eagain, NULL);
continue; // temporary failure. should retry
}
}
else
{
@@ -447,14 +453,18 @@ int dns_parse_query()
static void exithelp(void)
{
printf(
" --threads=<threads_number>\n"
" --family=<4|6|46>\t\t; ipv4, ipv6, ipv4+ipv6\n"
" --threads=<threads_number>\n"
" --eagain=<eagain_retries>\t; how many times to retry if EAI_AGAIN received. default %u\n"
" --eagain-delay=<ms>\t\t; time in msec to wait between EAI_AGAIN attempts. default %u\n"
" --verbose\t\t\t; print query progress to stderr\n"
" --stats=N\t\t\t; print resolve stats to stderr every N domains\n"
" --log-resolved=<file>\t\t; log successfully resolved domains to a file\n"
" --log-failed=<file>\t\t; log failed domains to a file\n"
" --dns-make-query=<domain>\t; output to stdout binary blob with DNS query. use --family to specify ip version.\n"
" --dns-parse-query\t\t; read from stdin binary DNS answer blob and parse it to ipv4/ipv6 addresses\n"
" --dns-parse-query\t\t; read from stdin binary DNS answer blob and parse it to ipv4/ipv6 addresses\n",
RESOLVER_EAGAIN_ATTEMPTS,
RESOLVER_EAGAIN_DELAY
);
exit(1);
}
@@ -469,6 +479,8 @@ static void exithelp(void)
enum opt_indices {
IDX_HELP,
IDX_EAGAIN,
IDX_EAGAIN_DELAY,
IDX_THREADS,
IDX_FAMILY,
IDX_VERBOSE,
@@ -483,6 +495,8 @@ enum opt_indices {
static const struct option long_options[] = {
[IDX_HELP] = {"help", no_argument, 0, 0},
[IDX_THREADS] = {"threads", required_argument, 0, 0},
[IDX_EAGAIN] = {"eagain", required_argument, 0, 0},
[IDX_EAGAIN_DELAY] = {"eagain-delay", 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},
@@ -503,6 +517,8 @@ int main(int argc, char **argv)
*fn1 = *fn2 = *dom = 0;
glob.family = FAMILY4;
glob.threads = 1;
glob.eagain = RESOLVER_EAGAIN_ATTEMPTS;
glob.eagain_delay = RESOLVER_EAGAIN_DELAY;
while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
{
if (v) exithelp();
@@ -513,13 +529,29 @@ int main(int argc, char **argv)
exithelp();
break;
case IDX_THREADS:
glob.threads = optarg ? atoi(optarg) : 0;
glob.threads = atoi(optarg);
if (glob.threads <= 0 || glob.threads > 100)
{
fprintf(stderr, "thread number must be within 1..100\n");
return 1;
}
break;
case IDX_EAGAIN:
glob.eagain = atoi(optarg);
if (glob.eagain <= 0 || glob.eagain > 1000)
{
fprintf(stderr, "eagain must be within 1..1000\n");
return 1;
}
break;
case IDX_EAGAIN_DELAY:
glob.eagain_delay = atoi(optarg);
if (glob.eagain_delay < 0 || glob.eagain_delay > 100000)
{
fprintf(stderr, "eagain-delay must be within 0..100000\n");
return 1;
}
break;
case IDX_FAMILY:
if (!strcmp(optarg, "4"))
glob.family = FAMILY4;

View File

@@ -2,64 +2,65 @@
#include "checksum.h"
#include <netinet/in.h>
//#define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
//#define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
// #define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
// #define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
static uint16_t from64to16(uint64_t x)
{
uint32_t u = (uint32_t)(uint16_t)x + (uint16_t)(x>>16) + (uint16_t)(x>>32) + (uint16_t)(x>>48);
return (uint16_t)u + (uint16_t)(u>>16);
uint32_t u = (uint32_t)(uint16_t)x + (uint16_t)(x >> 16) + (uint16_t)(x >> 32) + (uint16_t)(x >> 48);
return (uint16_t)u + (uint16_t)(u >> 16);
}
// this function preserves data alignment requirements (otherwise it will be damn slow on mips arch)
// and uses 64-bit arithmetics to improve speed
// taken from linux source code
static uint16_t do_csum(const uint8_t * buff, size_t len)
static uint16_t do_csum(const uint8_t *buff, size_t len)
{
uint8_t odd;
size_t count;
uint64_t result,w,carry=0;
uint64_t result, w, carry = 0;
uint16_t u16;
if (!len) return 0;
if (!len)
return 0;
odd = (uint8_t)(1 & (size_t)buff);
if (odd)
{
// any endian compatible
u16 = 0;
*((uint8_t*)&u16+1) = *buff;
*((uint8_t *)&u16 + 1) = *buff;
result = u16;
len--;
buff++;
}
else
result = 0;
count = len >> 1; /* nr of 16-bit words.. */
count = len >> 1; /* nr of 16-bit words.. */
if (count)
{
if (2 & (size_t) buff)
if (2 & (size_t)buff)
{
result += *(uint16_t *) buff;
result += *(uint16_t *)buff;
count--;
len -= 2;
buff += 2;
}
count >>= 1; /* nr of 32-bit words.. */
count >>= 1; /* nr of 32-bit words.. */
if (count)
{
if (4 & (size_t) buff)
if (4 & (size_t)buff)
{
result += *(uint32_t *) buff;
result += *(uint32_t *)buff;
count--;
len -= 4;
buff += 4;
}
count >>= 1; /* nr of 64-bit words.. */
count >>= 1; /* nr of 64-bit words.. */
if (count)
{
do
{
w = *(uint64_t *) buff;
w = *(uint64_t *)buff;
count--;
buff += 8;
result += carry;
@@ -71,13 +72,13 @@ static uint16_t do_csum(const uint8_t * buff, size_t len)
}
if (len & 4)
{
result += *(uint32_t *) buff;
result += *(uint32_t *)buff;
buff += 4;
}
}
if (len & 2)
{
result += *(uint16_t *) buff;
result += *(uint16_t *)buff;
buff += 2;
}
}
@@ -85,54 +86,54 @@ static uint16_t do_csum(const uint8_t * buff, size_t len)
{
// any endian compatible
u16 = 0;
*(uint8_t*)&u16 = *buff;
*(uint8_t *)&u16 = *buff;
result += u16;
}
u16 = from64to16(result);
if (odd) u16 = ((u16 >> 8) & 0xff) | ((u16 & 0xff) << 8);
if (odd)
u16 = ((u16 >> 8) & 0xff) | ((u16 & 0xff) << 8);
return u16;
}
uint16_t csum_partial(const void *buff, size_t len)
{
return do_csum(buff,len);
return do_csum(buff, len);
}
uint16_t csum_tcpudp_magic(uint32_t saddr, uint32_t daddr, size_t len, uint8_t proto, uint16_t sum)
{
return ~from64to16((uint64_t)saddr + daddr + sum + htonl(len+proto));
return ~from64to16((uint64_t)saddr + daddr + sum + htonl(len + proto));
}
uint16_t ip4_compute_csum(const void *buff, size_t len)
{
return ~from64to16(do_csum(buff,len));
return ~from64to16(do_csum(buff, len));
}
void ip4_fix_checksum(struct ip *ip)
{
ip->ip_sum = 0;
ip->ip_sum = ip4_compute_csum(ip, ip->ip_hl<<2);
ip->ip_sum = ip4_compute_csum(ip, ip->ip_hl << 2);
}
uint16_t csum_ipv6_magic(const void *saddr, const void *daddr, size_t len, uint8_t proto, uint16_t sum)
{
uint64_t a = (uint64_t)sum + htonl(len+proto) +
*(uint32_t*)saddr + *((uint32_t*)saddr+1) + *((uint32_t*)saddr+2) + *((uint32_t*)saddr+3) +
*(uint32_t*)daddr + *((uint32_t*)daddr+1) + *((uint32_t*)daddr+2) + *((uint32_t*)daddr+3);
uint64_t a = (uint64_t)sum + htonl(len + proto) +
*(uint32_t *)saddr + *((uint32_t *)saddr + 1) + *((uint32_t *)saddr + 2) + *((uint32_t *)saddr + 3) +
*(uint32_t *)daddr + *((uint32_t *)daddr + 1) + *((uint32_t *)daddr + 2) + *((uint32_t *)daddr + 3);
return ~from64to16(a);
}
void tcp4_fix_checksum(struct tcphdr *tcp,size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr)
void tcp4_fix_checksum(struct tcphdr *tcp, size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr)
{
tcp->th_sum = 0;
tcp->th_sum = csum_tcpudp_magic(src_addr->s_addr,dest_addr->s_addr,len,IPPROTO_TCP,csum_partial(tcp,len));
tcp->th_sum = csum_tcpudp_magic(src_addr->s_addr, dest_addr->s_addr, len, IPPROTO_TCP, csum_partial(tcp, len));
}
void tcp6_fix_checksum(struct tcphdr *tcp,size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
void tcp6_fix_checksum(struct tcphdr *tcp, size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
{
tcp->th_sum = 0;
tcp->th_sum = csum_ipv6_magic(src_addr,dest_addr,len,IPPROTO_TCP,csum_partial(tcp,len));
tcp->th_sum = csum_ipv6_magic(src_addr, dest_addr, len, IPPROTO_TCP, csum_partial(tcp, len));
}
void tcp_fix_checksum(struct tcphdr *tcp,size_t len,const struct ip *ip,const struct ip6_hdr *ip6hdr)
void tcp_fix_checksum(struct tcphdr *tcp, size_t len, const struct ip *ip, const struct ip6_hdr *ip6hdr)
{
if (ip)
tcp4_fix_checksum(tcp, len, &ip->ip_src, &ip->ip_dst);
@@ -140,17 +141,17 @@ void tcp_fix_checksum(struct tcphdr *tcp,size_t len,const struct ip *ip,const st
tcp6_fix_checksum(tcp, len, &ip6hdr->ip6_src, &ip6hdr->ip6_dst);
}
void udp4_fix_checksum(struct udphdr *udp,size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr)
void udp4_fix_checksum(struct udphdr *udp, size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr)
{
udp->uh_sum = 0;
udp->uh_sum = csum_tcpudp_magic(src_addr->s_addr,dest_addr->s_addr,len,IPPROTO_UDP,csum_partial(udp,len));
udp->uh_sum = csum_tcpudp_magic(src_addr->s_addr, dest_addr->s_addr, len, IPPROTO_UDP, csum_partial(udp, len));
}
void udp6_fix_checksum(struct udphdr *udp,size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
void udp6_fix_checksum(struct udphdr *udp, size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
{
udp->uh_sum = 0;
udp->uh_sum = csum_ipv6_magic(src_addr,dest_addr,len,IPPROTO_UDP,csum_partial(udp,len));
udp->uh_sum = csum_ipv6_magic(src_addr, dest_addr, len, IPPROTO_UDP, csum_partial(udp, len));
}
void udp_fix_checksum(struct udphdr *udp,size_t len,const struct ip *ip,const struct ip6_hdr *ip6hdr)
void udp_fix_checksum(struct udphdr *udp, size_t len, const struct ip *ip, const struct ip6_hdr *ip6hdr)
{
if (ip)
udp4_fix_checksum(udp, len, &ip->ip_src, &ip->ip_dst);

View File

@@ -37,7 +37,7 @@ void ConntrackClearHostname(t_ctrack *track)
static void ConntrackClearTrack(t_ctrack *track)
{
ConntrackClearHostname(track);
ReasmClear(&track->reasm_orig);
ReasmClear(&track->reasm_client);
rawpacket_queue_destroy(&track->delayed);
luaL_unref(params.L, LUA_REGISTRYINDEX, track->lua_state);
luaL_unref(params.L, LUA_REGISTRYINDEX, track->lua_instance_cutoff);
@@ -70,24 +70,24 @@ void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_s
p->pool = NULL;
}
void ConntrackExtractConn(t_conn *c, bool bReverse, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr)
void ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis)
{
memset(c, 0, sizeof(*c));
if (ip)
if (dis->ip)
{
c->l3proto = IPPROTO_IP;
c->dst.ip = bReverse ? ip->ip_src : ip->ip_dst;
c->src.ip = bReverse ? ip->ip_dst : ip->ip_src;
c->dst.ip = bReverse ? dis->ip->ip_src : dis->ip->ip_dst;
c->src.ip = bReverse ? dis->ip->ip_dst : dis->ip->ip_src;
}
else if (ip6)
else if (dis->ip6)
{
c->l3proto = IPPROTO_IPV6;
c->dst.ip6 = bReverse ? ip6->ip6_src : ip6->ip6_dst;
c->src.ip6 = bReverse ? ip6->ip6_dst : ip6->ip6_src;
c->dst.ip6 = bReverse ? dis->ip6->ip6_src : dis->ip6->ip6_dst;
c->src.ip6 = bReverse ? dis->ip6->ip6_dst : dis->ip6->ip6_src;
}
else
c->l3proto = -1;
extract_ports(tcphdr, udphdr, &c->l4proto, bReverse ? &c->dport : &c->sport, bReverse ? &c->sport : &c->dport);
extract_ports(dis->tcp, dis->udp, &c->l4proto, bReverse ? &c->dport : &c->sport, bReverse ? &c->sport : &c->dport);
}
@@ -102,8 +102,7 @@ static void ConntrackInitTrack(t_ctrack *t)
{
memset(t, 0, sizeof(*t));
t->l7proto = L7_UNKNOWN;
t->pos.scale_orig = t->pos.scale_reply = SCALE_NONE;
time(&t->pos.t_start);
t->pos.client.scale = t->pos.server.scale = SCALE_NONE;
rawpacket_queue_init(&t->delayed);
lua_newtable(params.L);
t->lua_state = luaL_ref(params.L, LUA_REGISTRYINDEX);
@@ -128,43 +127,79 @@ static t_conntrack_pool *ConntrackNew(t_conntrack_pool **pp, const t_conn *c)
return ctnew;
}
// non-tcp packets are passed with tcphdr=NULL but len_payload filled
static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr *tcphdr, uint32_t len_payload)
static void ConntrackApplyPos(t_ctrack *t, bool bReverse, const struct dissect *dis)
{
uint8_t scale;
uint16_t mss;
t_ctrack_position *direct, *reverse;
direct = bReverse ? &t->pos.server : &t->pos.client;
reverse = bReverse ? &t->pos.client : &t->pos.server;
if (dis->ip6) direct->ip6flow = ntohl(dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_flow);
scale = tcp_find_scale_factor(dis->tcp);
mss = ntohs(tcp_find_mss(dis->tcp));
direct->seq_last = ntohl(dis->tcp->th_seq);
direct->pos = direct->seq_last + dis->len_payload;
reverse->pos = reverse->seq_last = ntohl(dis->tcp->th_ack);
if (t->pos.state == SYN)
direct->uppos_prev = direct->uppos = direct->pos;
else if (dis->len_payload)
{
direct->uppos_prev = direct->uppos;
if (!((direct->pos - direct->uppos) & 0x80000000))
direct->uppos = direct->pos;
}
direct->winsize = ntohs(dis->tcp->th_win);
direct->winsize_calc = direct->winsize;
if (direct->scale != SCALE_NONE) direct->winsize_calc <<= direct->scale;
if (mss && !direct->mss) direct->mss = mss;
if (scale != SCALE_NONE) direct->scale = scale;
if (!direct->rseq_over_2G && ((direct->seq_last - direct->seq0) & 0x80000000))
direct->rseq_over_2G = true;
if (!reverse->rseq_over_2G && ((reverse->seq_last - reverse->seq0) & 0x80000000))
reverse->rseq_over_2G = true;
}
static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct dissect *dis)
{
uint8_t scale;
uint16_t mss;
if (bReverse)
{
t->pos.pcounter_reply++;
t->pos.pdcounter_reply += !!len_payload;
t->pos.pbcounter_reply += len_payload;
t->pos.server.pcounter++;
t->pos.server.pdcounter += !!dis->len_payload;
t->pos.server.pbcounter += dis->len_payload;
}
else
{
t->pos.pcounter_orig++;
t->pos.pdcounter_orig += !!len_payload;
t->pos.pbcounter_orig += len_payload;
t->pos.client.pcounter++;
t->pos.client.pdcounter += !!dis->len_payload;
t->pos.client.pbcounter += dis->len_payload;
}
if (tcphdr)
if (dis->tcp)
{
if (tcp_syn_segment(tcphdr))
if (tcp_syn_segment(dis->tcp))
{
if (t->pos.state != SYN) ConntrackReInitTrack(t); // erase current entry
t->pos.seq0 = ntohl(tcphdr->th_seq);
t->pos.client.seq0 = ntohl(dis->tcp->th_seq);
}
else if (tcp_synack_segment(tcphdr))
else if (tcp_synack_segment(dis->tcp))
{
// ignore SA dups
uint32_t seq0 = ntohl(tcphdr->th_ack) - 1;
if (t->pos.state != SYN && t->pos.seq0 != seq0)
uint32_t seq0 = ntohl(dis->tcp->th_ack) - 1;
if (t->pos.state != SYN && t->pos.client.seq0 != seq0)
ConntrackReInitTrack(t); // erase current entry
if (!t->pos.seq0) t->pos.seq0 = seq0;
t->pos.ack0 = ntohl(tcphdr->th_seq);
if (!t->pos.client.seq0) t->pos.client.seq0 = seq0;
t->pos.server.seq0 = ntohl(dis->tcp->th_seq);
}
else if (tcphdr->th_flags & (TH_FIN | TH_RST))
else if (dis->tcp->th_flags & (TH_FIN | TH_RST))
{
t->pos.state = FIN;
}
@@ -173,57 +208,24 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
if (t->pos.state == SYN)
{
t->pos.state = ESTABLISHED;
if (!bReverse && !t->pos.ack0) t->pos.ack0 = ntohl(tcphdr->th_ack) - 1;
if (!bReverse && !t->pos.server.seq0) t->pos.server.seq0 = ntohl(dis->tcp->th_ack) - 1;
}
}
scale = tcp_find_scale_factor(tcphdr);
mss = ntohs(tcp_find_mss(tcphdr));
if (bReverse)
{
t->pos.pos_orig = t->pos.seq_last = ntohl(tcphdr->th_ack);
t->pos.ack_last = ntohl(tcphdr->th_seq);
t->pos.pos_reply = t->pos.ack_last + len_payload;
t->pos.winsize_reply = ntohs(tcphdr->th_win);
t->pos.winsize_reply_calc = t->pos.winsize_reply;
if (t->pos.scale_reply != SCALE_NONE) t->pos.winsize_reply_calc <<= t->pos.scale_reply;
if (mss && !t->pos.mss_reply) t->pos.mss_reply = mss;
if (scale != SCALE_NONE) t->pos.scale_reply = scale;
}
else
{
t->pos.seq_last = ntohl(tcphdr->th_seq);
t->pos.pos_orig = t->pos.seq_last + len_payload;
t->pos.pos_reply = t->pos.ack_last = ntohl(tcphdr->th_ack);
t->pos.winsize_orig = ntohs(tcphdr->th_win);
t->pos.winsize_orig_calc = t->pos.winsize_orig;
if (t->pos.scale_orig != SCALE_NONE) t->pos.winsize_orig_calc <<= t->pos.scale_orig;
if (mss && !t->pos.mss_reply) t->pos.mss_orig = mss;
if (scale != SCALE_NONE) t->pos.scale_orig = scale;
}
}
else
{
if (bReverse)
{
t->pos.ack_last = t->pos.pos_reply;
t->pos.pos_reply += len_payload;
}
else
{
t->pos.seq_last = t->pos.pos_orig;
t->pos.pos_orig += len_payload;
}
ConntrackApplyPos(t, bReverse, dis);
}
time(&t->pos.t_last);
clock_gettime(CLOCK_REALTIME, &t->pos.t_last);
// make sure t_start gets exactly the same value as first t_last
if (!t->t_start.tv_sec) t->t_start = t->pos.t_last;
}
static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse)
static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse)
{
t_conn conn, connswp;
t_conntrack_pool *ctr;
ConntrackExtractConn(&conn, false, ip, ip6, tcphdr, udphdr);
ConntrackExtractConn(&conn, false, dis);
if ((ctr = ConntrackPoolSearch(*pp, &conn)))
{
if (bReverse) *bReverse = false;
@@ -242,22 +244,22 @@ static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct ip
}
return false;
}
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse)
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse)
{
return ConntrackPoolDoubleSearchPool(&p->pool, ip, ip6, tcphdr, udphdr, ctrack, bReverse);
return ConntrackPoolDoubleSearchPool(&p->pool, dis, ctrack, bReverse);
}
static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse)
static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse)
{
t_conn conn, connswp;
t_conntrack_pool *ctr;
bool b_rev;
uint8_t proto = tcphdr ? IPPROTO_TCP : udphdr ? IPPROTO_UDP : IPPROTO_NONE;
uint8_t proto = dis->tcp ? IPPROTO_TCP : dis->udp ? IPPROTO_UDP : IPPROTO_NONE;
ConntrackExtractConn(&conn, false, ip, ip6, tcphdr, udphdr);
ConntrackExtractConn(&conn, false, dis);
if ((ctr = ConntrackPoolSearch(*pp, &conn)))
{
ConntrackFeedPacket(&ctr->track, (b_rev = false), tcphdr, len_payload);
ConntrackFeedPacket(&ctr->track, (b_rev = false), dis);
goto ok;
}
else
@@ -265,16 +267,16 @@ static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, const struct ip *ip, co
connswap(&conn, &connswp);
if ((ctr = ConntrackPoolSearch(*pp, &connswp)))
{
ConntrackFeedPacket(&ctr->track, (b_rev = true), tcphdr, len_payload);
ConntrackFeedPacket(&ctr->track, (b_rev = true), dis);
goto ok;
}
}
b_rev = tcphdr && tcp_synack_segment(tcphdr);
if ((tcphdr && tcp_syn_segment(tcphdr)) || b_rev || udphdr)
b_rev = dis->tcp && tcp_synack_segment(dis->tcp);
if ((dis->tcp && tcp_syn_segment(dis->tcp)) || b_rev || dis->udp)
{
if ((ctr = ConntrackNew(pp, b_rev ? &connswp : &conn)))
{
ConntrackFeedPacket(&ctr->track, b_rev, tcphdr, len_payload);
ConntrackFeedPacket(&ctr->track, b_rev, dis);
goto ok;
}
}
@@ -285,16 +287,16 @@ ok:
if (bReverse) *bReverse = b_rev;
return true;
}
bool ConntrackPoolFeed(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse)
bool ConntrackPoolFeed(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse)
{
return ConntrackPoolFeedPool(&p->pool, ip, ip6, tcphdr, udphdr, len_payload, ctrack, bReverse);
return ConntrackPoolFeedPool(&p->pool, dis, ctrack, bReverse);
}
static bool ConntrackPoolDropPool(t_conntrack_pool **pp, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr)
static bool ConntrackPoolDropPool(t_conntrack_pool **pp, const struct dissect *dis)
{
t_conn conn, connswp;
t_conntrack_pool *t;
ConntrackExtractConn(&conn, false, ip, ip6, tcphdr, udphdr);
ConntrackExtractConn(&conn, false, dis);
if (!(t = ConntrackPoolSearch(*pp, &conn)))
{
connswap(&conn, &connswp);
@@ -304,20 +306,22 @@ static bool ConntrackPoolDropPool(t_conntrack_pool **pp, const struct ip *ip, co
HASH_DEL(*pp, t); ConntrackFreeElem(t);
return true;
}
bool ConntrackPoolDrop(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr)
bool ConntrackPoolDrop(t_conntrack *p, const struct dissect *dis)
{
return ConntrackPoolDropPool(&p->pool, ip, ip6, tcphdr, udphdr);
return ConntrackPoolDropPool(&p->pool, dis);
}
void ConntrackPoolPurge(t_conntrack *p)
{
time_t tidle, tnow = time(NULL);
time_t tidle;
struct timespec tnow;
t_conntrack_pool *t, *tmp;
if ((tnow - p->t_last_purge) >= p->t_purge_interval)
if (clock_gettime(CLOCK_REALTIME, &tnow)) return;
if ((tnow.tv_sec - p->t_last_purge) >= p->t_purge_interval)
{
HASH_ITER(hh, p->pool, t, tmp) {
tidle = tnow - t->track.pos.t_last;
tidle = tnow.tv_sec - t->track.pos.t_last.tv_sec;
if (t->track.b_cutoff ||
(t->conn.l4proto == IPPROTO_TCP && (
(t->track.pos.state == SYN && tidle >= p->timeout_syn) ||
@@ -329,7 +333,7 @@ void ConntrackPoolPurge(t_conntrack *p)
HASH_DEL(p->pool, t); ConntrackFreeElem(t);
}
}
p->t_last_purge = tnow;
p->t_last_purge = tnow.tv_sec;
}
}
@@ -341,29 +345,31 @@ static void taddr2str(uint8_t l3proto, const t_addr *a, char *buf, size_t bufsiz
void ConntrackPoolDump(const t_conntrack *p)
{
t_conntrack_pool *t, *tmp;
struct timespec tnow;
char sa1[40], sa2[40];
time_t tnow = time(NULL);
if (clock_gettime(CLOCK_REALTIME, &tnow)) return;
HASH_ITER(hh, p->pool, t, tmp) {
taddr2str(t->conn.l3proto, &t->conn.src, sa1, sizeof(sa1));
taddr2str(t->conn.l3proto, &t->conn.dst, sa2, sizeof(sa2));
printf("%s [%s]:%u => [%s]:%u : %s : t0=%llu last=t0+%llu now=last+%llu orig=d%llu/n%llu/b%llu reply=d%llu/n%llu/b%lld ",
printf("%s [%s]:%u => [%s]:%u : %s : t0=%llu last=t0+%llu now=last+%llu client=d%llu/n%llu/b%llu server=d%llu/n%llu/b%lld ",
proto_name(t->conn.l4proto),
sa1, t->conn.sport, sa2, t->conn.dport,
t->conn.l4proto == IPPROTO_TCP ? connstate_s[t->track.pos.state] : "-",
(unsigned long long)t->track.pos.t_start, (unsigned long long)(t->track.pos.t_last - t->track.pos.t_start), (unsigned long long)(tnow - t->track.pos.t_last),
(unsigned long long)t->track.pos.pdcounter_orig, (unsigned long long)t->track.pos.pcounter_orig, (unsigned long long)t->track.pos.pbcounter_orig,
(unsigned long long)t->track.pos.pdcounter_reply, (unsigned long long)t->track.pos.pcounter_reply, (unsigned long long)t->track.pos.pbcounter_reply);
(unsigned long long)t->track.t_start.tv_sec, (unsigned long long)(t->track.pos.t_last.tv_sec - t->track.t_start.tv_sec), (unsigned long long)(tnow.tv_sec - t->track.pos.t_last.tv_sec),
(unsigned long long)t->track.pos.client.pdcounter, (unsigned long long)t->track.pos.client.pcounter, (unsigned long long)t->track.pos.client.pbcounter,
(unsigned long long)t->track.pos.server.pdcounter, (unsigned long long)t->track.pos.server.pcounter, (unsigned long long)t->track.pos.server.pbcounter);
if (t->conn.l4proto == IPPROTO_TCP)
printf("seq0=%u rseq=%u pos_orig=%u ack0=%u rack=%u pos_reply=%u mss_orig=%u mss_reply=%u wsize_orig=%u:%d wsize_reply=%u:%d",
t->track.pos.seq0, t->track.pos.seq_last - t->track.pos.seq0, t->track.pos.pos_orig - t->track.pos.seq0,
t->track.pos.ack0, t->track.pos.ack_last - t->track.pos.ack0, t->track.pos.pos_reply - t->track.pos.ack0,
t->track.pos.mss_orig, t->track.pos.mss_reply,
t->track.pos.winsize_orig, t->track.pos.scale_orig == SCALE_NONE ? -1 : t->track.pos.scale_orig,
t->track.pos.winsize_reply, t->track.pos.scale_reply == SCALE_NONE ? -1 : t->track.pos.scale_reply);
printf("seq0=%u rseq=%u client.pos=%u ack0=%u rack=%u server.pos=%u client.mss=%u server.mss=%u client.wsize=%u:%d server.wsize=%u:%d",
t->track.pos.client.seq0, t->track.pos.client.seq_last - t->track.pos.client.seq0, t->track.pos.client.pos - t->track.pos.client.seq0,
t->track.pos.server.seq0, t->track.pos.server.seq_last - t->track.pos.server.seq0, t->track.pos.server.pos - t->track.pos.server.seq0,
t->track.pos.client.mss, t->track.pos.server.mss,
t->track.pos.client.winsize, t->track.pos.client.scale == SCALE_NONE ? -1 : t->track.pos.client.scale,
t->track.pos.server.winsize, t->track.pos.server.scale == SCALE_NONE ? -1 : t->track.pos.server.scale);
else
printf("rseq=%u pos_orig=%u rack=%u pos_reply=%u",
t->track.pos.seq_last, t->track.pos.pos_orig,
t->track.pos.ack_last, t->track.pos.pos_reply);
printf("rseq=%u client.pos=%u rack=%u server.pos=%u",
t->track.pos.client.seq_last, t->track.pos.client.pos,
t->track.pos.server.seq_last, t->track.pos.server.pos);
printf(" req_retrans=%u cutoff=%u lua_in_cutoff=%u lua_out_cutoff=%u hostname=%s l7proto=%s\n",
t->track.req_retrans_counter, t->track.b_cutoff, t->track.b_lua_in_cutoff, t->track.b_lua_out_cutoff, t->track.hostname, l7proto_str(t->track.l7proto));
};
@@ -394,17 +400,30 @@ bool ReasmResize(t_reassemble *reasm, size_t new_size)
if (reasm->size_present > new_size) reasm->size_present = new_size;
return true;
}
#define REASM_MAX_NEG 0x100000
bool ReasmFeed(t_reassemble *reasm, uint32_t seq, const void *payload, size_t len)
{
if (reasm->seq != seq) return false; // fail session if out of sequence
size_t szcopy;
szcopy = reasm->size - reasm->size_present;
if (len < szcopy) szcopy = len;
memcpy(reasm->packet + reasm->size_present, payload, szcopy);
reasm->size_present += szcopy;
reasm->seq += (uint32_t)szcopy;
uint32_t dseq = seq - reasm->seq;
if (dseq && (dseq < REASM_MAX_NEG))
return false; // fail session if a gap about to appear
uint32_t neg_overlap = reasm->seq - seq;
if (neg_overlap > REASM_MAX_NEG)
return false; // too big minus
size_t szcopy, szignore;
szignore = (neg_overlap > reasm->size_present) ? neg_overlap - reasm->size_present : 0;
if (szignore>=len) return true; // everyting is before the starting pos
szcopy = len - szignore;
neg_overlap -= szignore;
if ((reasm->size_present - neg_overlap + szcopy) > reasm->size)
return false; // buffer overflow
// in case of seq overlap new data replaces old - unix behavior
memcpy(reasm->packet + reasm->size_present - neg_overlap, payload + szignore, szcopy);
if (szcopy>neg_overlap)
{
reasm->size_present += szcopy - neg_overlap;
reasm->seq += (uint32_t)szcopy - neg_overlap;
}
return true;
}
bool ReasmHasSpace(t_reassemble *reasm, size_t len)

View File

@@ -19,6 +19,7 @@
#include "conntrack_base.h"
#include "packet_queue.h"
#include "protocol.h"
#include "darkmagic.h"
//#define HASH_BLOOM 20
#define HASH_NONFATAL_OOM 1
@@ -43,7 +44,7 @@ typedef struct
// this structure helps to reassemble continuous packets streams. it does not support out-of-orders
typedef struct {
uint8_t *packet; // allocated for size during reassemble request. requestor must know the message size.
uint32_t seq; // current seq number. if a packet comes with an unexpected seq - it fails reassemble session.
uint32_t seq; // current seq number. if a packet comes with unsupported seq overlap - it fails reassemble session.
size_t size; // expected message size. success means that we have received exactly 'size' bytes and have them in 'packet'
size_t size_present; // how many bytes already stored in 'packet'
} t_reassemble;
@@ -54,15 +55,16 @@ typedef struct
bool bCheckDone, bCheckResult, bCheckExcluded; // hostlist check result cache
uint8_t ipproto;
struct timespec t_start;
// this block of data can change between delayed (queued) packets. need to remeber this data for each packet for further replay
t_ctrack_position pos;
t_ctrack_positions pos;
struct desync_profile *dp; // desync profile cache
bool dp_search_complete;
uint8_t req_retrans_counter; // number of request retransmissions
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)
bool failure_detect_finalized;
uint8_t incoming_ttl;
@@ -79,7 +81,7 @@ typedef struct
int lua_state; // registry index of associated LUA object
int lua_instance_cutoff; // registry index of per connection function instance cutoff table
t_reassemble reasm_orig;
t_reassemble reasm_client;
struct rawpacket_tailhead delayed;
} t_ctrack;
@@ -99,11 +101,11 @@ typedef struct
void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_syn, uint32_t timeout_established, uint32_t timeout_fin, uint32_t timeout_udp);
void ConntrackPoolDestroy(t_conntrack *p);
bool ConntrackPoolFeed(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse);
bool ConntrackPoolFeed(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse);
// do not create, do not update. only find existing
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse);
bool ConntrackPoolDrop(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr);
void CaonntrackExtractConn(t_conn *c, bool bReverse, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr);
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse);
bool ConntrackPoolDrop(t_conntrack *p, const struct dissect *dis);
void ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis);
void ConntrackPoolDump(const t_conntrack *p);
void ConntrackPoolPurge(t_conntrack *p);
void ConntrackClearHostname(t_ctrack *track);

View File

@@ -1,5 +1,6 @@
#pragma once
#include <stdint.h>
#include <time.h>
#define CTRACK_T_SYN 60
@@ -14,19 +15,28 @@ typedef enum {SYN=0, ESTABLISHED, FIN} t_connstate;
typedef struct
{
time_t t_last, t_start;
uint64_t pcounter_orig, pcounter_reply; // packet counter
uint64_t pdcounter_orig, pdcounter_reply; // data packet counter (with payload)
uint64_t pbcounter_orig, pbcounter_reply; // transferred byte counter. includes retransmissions. it's not the same as relative seq.
uint32_t pos_orig, pos_reply; // TCP: seq_last+payload, ack_last+payload UDP: sum of all seen payload lenghts including current
uint32_t seq_last, ack_last; // TCP: last seen seq and ack UDP: sum of all seen payload lenghts NOT including current
uint64_t pcounter; // packet counter
uint64_t pdcounter; // data packet counter (with payload)
uint64_t pbcounter; // transferred byte counter. includes retransmissions. it's not the same as relative seq.
uint32_t ip6flow;
// tcp only state, not used in udp
t_connstate state;
uint32_t seq0, ack0; // starting seq and ack
uint16_t winsize_orig, winsize_reply; // last seen window size
uint8_t scale_orig, scale_reply; // last seen window scale factor. SCALE_NONE if none
uint32_t winsize_orig_calc, winsize_reply_calc; // calculated window size
uint16_t mss_orig, mss_reply;
uint32_t pos; // TCP: seq_last+payload, ack_last+payload UDP: sum of all seen payload lenghts including current
uint32_t uppos; // max seen position. useful to detect retransmissions
uint32_t uppos_prev; // previous max seen position. useful to detect retransmissions
uint32_t seq_last; // TCP: last seen seq and ack UDP: sum of all seen payload lenghts NOT including current
uint32_t seq0; // starting seq and ack
uint16_t winsize; // last seen window size
uint16_t mss;
uint32_t winsize_calc; // calculated window size
uint8_t scale; // last seen window scale factor. SCALE_NONE if none
bool rseq_over_2G;
} t_ctrack_position;
typedef struct
{
struct timespec t_last;
t_connstate state;
t_ctrack_position client, server;
}
t_ctrack_positions;

View File

@@ -40,9 +40,6 @@
#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)
@@ -54,11 +51,6 @@ 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,11 +75,6 @@ uint8_t *tcp_find_option(struct tcphdr *tcp, uint8_t kind)
}
return NULL;
}
uint32_t *tcp_find_timestamps(struct tcphdr *tcp)
{
uint8_t *t = tcp_find_option(tcp, TCP_KIND_TS);
return (t && t[1]==10) ? (uint32_t*)(t+2) : NULL;
}
uint8_t tcp_find_scale_factor(const struct tcphdr *tcp)
{
uint8_t *scale = tcp_find_option((struct tcphdr*)tcp, TCP_KIND_SCALE);
@@ -550,6 +537,33 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis)
}
}
void reverse_ip(struct ip *ip, struct ip6_hdr *ip6)
{
if (ip)
{
struct in_addr temp = ip->ip_src;
ip->ip_src = ip->ip_dst;
ip->ip_dst = temp;
ip4_fix_checksum(ip);
}
if (ip6)
{
struct in6_addr temp = ip6->ip6_src;
ip6->ip6_src = ip6->ip6_dst;
ip6->ip6_dst = temp;
}
}
void reverse_tcp(struct tcphdr *tcp)
{
uint16_t tport = tcp->th_sport;
tcp->th_sport = tcp->th_dport;
tcp->th_dport = tport;
uint32_t tseq = tcp->th_seq;
tcp->th_seq = tcp->th_ack;
tcp->th_ack = tseq;
}
uint8_t ttl46(const struct ip *ip, const struct ip6_hdr *ip6)
{
@@ -608,7 +622,7 @@ BOOL LowMandatoryLevel(void)
label_low.Label.Sid = (PSID)buf1;
InitializeSid(label_low.Label.Sid, &label_authority, 1);
label_low.Label.Attributes = 0;
label_low.Label.Attributes = SE_GROUP_INTEGRITY;
*GetSidSubAuthority(label_low.Label.Sid, 0) = SECURITY_MANDATORY_LOW_RID;
// S-1-16-12288 : Mandatory Label\High Mandatory Level
@@ -721,13 +735,36 @@ bool prepare_low_appdata()
return b;
}
BOOL JobSandbox()
{
BOOL bRes = FALSE;
HANDLE hJob;
JOBOBJECT_BASIC_LIMIT_INFORMATION basic_limit;
JOBOBJECT_BASIC_UI_RESTRICTIONS basic_ui;
if (hJob = CreateJobObjectW(NULL, NULL))
{
basic_limit.LimitFlags = JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
// prevent child process creation
basic_limit.ActiveProcessLimit = 1;
// prevent some UI interaction and settings change
basic_ui.UIRestrictionsClass = JOB_OBJECT_UILIMIT_DESKTOP | JOB_OBJECT_UILIMIT_DISPLAYSETTINGS | JOB_OBJECT_UILIMIT_EXITWINDOWS | JOB_OBJECT_UILIMIT_GLOBALATOMS | JOB_OBJECT_UILIMIT_HANDLES | JOB_OBJECT_UILIMIT_READCLIPBOARD | JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS | JOB_OBJECT_UILIMIT_WRITECLIPBOARD;
bRes = SetInformationJobObject(hJob, JobObjectBasicLimitInformation, &basic_limit, sizeof(basic_limit)) &&
SetInformationJobObject(hJob, JobObjectBasicUIRestrictions, &basic_ui, sizeof(basic_ui)) &&
AssignProcessToJobObject(hJob, GetCurrentProcess());
w_win32_error = GetLastError();
CloseHandle(hJob);
}
return bRes;
}
#define WINDIVERT_DEVICE_NAME "WinDivert"
static bool b_isandbox_set = false;
static bool b_sandbox_set = false;
bool win_sandbox(void)
{
// there's no way to return privs
if (!b_isandbox_set)
if (!b_sandbox_set)
{
if (!RemoveTokenPrivs())
return FALSE;
@@ -737,8 +774,9 @@ bool win_sandbox(void)
return FALSE;
if (!LowMandatoryLevel())
return false;
// for LUA code to find where to store files
b_isandbox_set = true;
if (!JobSandbox())
return false;
b_sandbox_set = true;
}
return true;
}
@@ -854,7 +892,7 @@ bool win_dark_init(const struct str_list_head *ssid_filter, const struct str_lis
wlan_filter_ssid = ssid_filter;
return true;
}
bool win_dark_deinit(void)
void win_dark_deinit(void)
{
if (pNetworkListManager)
{
@@ -959,11 +997,12 @@ bool nlm_list(bool bAll)
}
else
bRet = false;
CoUninitialize();
}
else
bRet = false;
CoUninitialize();
return bRet;
}
@@ -1133,8 +1172,11 @@ static HANDLE windivert_init_filter(const char *filter, UINT64 flags)
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, w_win32_error, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), (LPSTR)&errormessage, 0, NULL);
DLOG_ERR("windivert: error opening filter: %s", errormessage);
LocalFree(errormessage);
if (errormessage)
{
DLOG_ERR("windivert: error opening filter: %s", errormessage);
LocalFree(errormessage);
}
if (w_win32_error == ERROR_INVALID_IMAGE_HASH)
DLOG_ERR("windivert: try to disable secure boot and install OS patches\n");
@@ -1256,14 +1298,21 @@ bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const char *ifout,const
{
WINDIVERT_ADDRESS wa;
if (!ifout) return false;
memset(&wa,0,sizeof(wa));
// pseudo interface id IfIdx.SubIfIdx
if (sscanf(ifout,"%u.%u",&wa.Network.IfIdx,&wa.Network.SubIfIdx)!=2)
if (ifout && *ifout)
{
errno = EINVAL;
return false;
if (sscanf(ifout,"%u.%u",&wa.Network.IfIdx,&wa.Network.SubIfIdx)!=2)
{
errno = EINVAL;
return false;
}
}
else
{
// 1 - typically loopback
wa.Network.IfIdx=1;
wa.Network.SubIfIdx=0;
}
wa.Outbound=1;
wa.IPChecksum=1;
@@ -1578,9 +1627,9 @@ bool rawsend_queue(struct rawpacket_tailhead *q)
// linux-specific wlan retrieval implementation
typedef void netlink_prepare_nlh_cb_t(struct nlmsghdr *nlh);
typedef void netlink_prepare_nlh_cb_t(struct nlmsghdr *nlh, void *param);
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)
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, void *prepare_data, mnl_cb_t cb_data, void *data)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
@@ -1595,7 +1644,7 @@ static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, u
genl->cmd = cmd;
genl->version = version;
if (cb_prepare_nlh) cb_prepare_nlh(nlh);
if (cb_prepare_nlh) cb_prepare_nlh(nlh, prepare_data);
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
{
@@ -1619,7 +1668,7 @@ static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, u
return false;
}
static void wlan_id_prepare(struct nlmsghdr *nlh)
static void wlan_id_prepare(struct nlmsghdr *nlh, void *param)
{
mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, "nl80211");
}
@@ -1651,7 +1700,7 @@ static int wlan_id_cb(const struct nlmsghdr *nlh, void *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;
return netlink_genl_simple_transact(nl, GENL_ID_CTRL, NLM_F_REQUEST | NLM_F_ACK, CTRL_CMD_GETFAMILY, 1, wlan_id_prepare, NULL, wlan_id_cb, &id) ? id : 0;
}
static int wlan_info_attr_cb(const struct nlattr *attr, void *data)
@@ -1686,42 +1735,130 @@ static int wlan_info_attr_cb(const struct nlattr *attr, void *data)
}
return MNL_CB_OK;
}
struct wlan_info_req
{
struct wlan_interface_collection *wc;
bool bReqSSID;
};
static int wlan_info_cb(const struct nlmsghdr *nlh, void *data)
{
int ret;
struct wlan_info_req *wr = (struct wlan_info_req*)data;
if (wr->wc->count>=WLAN_INTERFACE_MAX) return MNL_CB_OK;
memset(wr->wc->wlan + wr->wc->count,0,sizeof(struct wlan_interface));
ret = mnl_attr_parse(nlh, sizeof(struct genlmsghdr), wlan_info_attr_cb, wr->wc->wlan + wr->wc->count);
if (ret>=0 && (!wr->bReqSSID || *wr->wc->wlan[wr->wc->count].ssid) && *wr->wc->wlan[wr->wc->count].ifname && wr->wc->wlan[wr->wc->count].ifindex)
wr->wc->count++;
return ret;
}
static bool wlan_info(struct mnl_socket* nl, uint16_t wlan_family_id, struct wlan_interface_collection* w, bool bReqSSID)
{
struct wlan_info_req req = { .bReqSSID = bReqSSID, .wc = 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, NULL, wlan_info_cb, &req);
}
static void scan_prepare(struct nlmsghdr *nlh, void *param)
{
mnl_attr_put_u32(nlh, NL80211_ATTR_IFINDEX, *(int*)param);
}
static uint8_t *find_ie(uint8_t *buf, size_t len, uint8_t ie)
{
while (len>=2)
{
if (len<(2+buf[1])) break;
if (buf[0]==ie) return buf;
buf+=buf[1]+2;
len-=buf[1]+2;
}
return NULL;
}
static int scan_info_attr_cb(const struct nlattr *attr, void *data)
{
struct wlan_interface *wlan = (struct wlan_interface *)data;
const struct nlattr *nested;
uint8_t *payload, *ie;
uint16_t payload_len;
bool ok;
switch(mnl_attr_get_type(attr))
{
case NL80211_ATTR_IFINDEX:
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
{
DLOG_PERROR("mnl_attr_validate");
return MNL_CB_ERROR;
}
wlan->ifindex = mnl_attr_get_u32(attr);
if (!if_indextoname(wlan->ifindex, wlan->ifname))
DLOG_PERROR("if_indextoname");
break;
case NL80211_ATTR_BSS:
if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
{
DLOG_PERROR("mnl_attr_validate");
return MNL_CB_ERROR;
}
ok = false;
mnl_attr_for_each_nested(nested, attr)
{
if (mnl_attr_get_type(nested)==NL80211_BSS_STATUS)
{
uint32_t status = mnl_attr_get_u32(nested);
if (status==NL80211_BSS_STATUS_ASSOCIATED || status==NL80211_BSS_STATUS_AUTHENTICATED || status==NL80211_BSS_STATUS_IBSS_JOINED)
{
ok=1;
break;
}
}
}
if (!ok) break;
mnl_attr_for_each_nested(nested, attr)
{
switch(mnl_attr_get_type(nested))
{
case NL80211_BSS_INFORMATION_ELEMENTS:
payload_len = mnl_attr_get_payload_len(nested);
payload = mnl_attr_get_payload(nested);
ie = find_ie(payload,payload_len,0);
if (ie)
{
uint8_t l = ie[1];
if (l>=(sizeof(wlan->ssid))) l=sizeof(wlan->ssid)-1;
memcpy(wlan->ssid,ie+2,l);
wlan->ssid[l]=0;
}
break;
}
}
break;
}
return MNL_CB_OK;
}
static int scan_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);
}
}
}
ret = mnl_attr_parse(nlh, sizeof(struct genlmsghdr), scan_info_attr_cb, wc->wlan+wc->count);
if (ret>=0 && *wc->wlan[wc->count].ssid && *wc->wlan[wc->count].ifname && wc->wlan[wc->count].ifindex)
wc->count++;
return ret;
}
static bool wlan_info(struct mnl_socket* nl, uint16_t wlan_family_id, struct wlan_interface_collection* w)
static bool scan_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);
struct wlan_interface_collection wc_all = { .count = 0 };
// wlan_info does not return ssid since kernel 5.19
// it's used to enumerate all wifi interfaces then call scan_info on each
if (!wlan_info(nl, wlan_family_id, &wc_all, false)) return false;
for(int i=0;i<wc_all.count;i++)
if (!netlink_genl_simple_transact(nl, wlan_family_id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0, scan_prepare, (void*)&wc_all.wlan[i].ifindex, scan_info_cb, w))
return false;
return true;
}
static bool wlan_init80211(struct mnl_socket** nl)
{
if (!(*nl = mnl_socket_open(NETLINK_GENERIC)))
@@ -1755,7 +1892,7 @@ static bool wlan_info_rate_limited(struct mnl_socket* nl, uint16_t wlan_family_i
// do not purge too often to save resources
if (wlan_info_last != now)
{
bres = wlan_info(nl,wlan_family_id,w);
bres = scan_info(nl,wlan_family_id,w);
wlan_info_last = now;
}
return bres;
@@ -1781,10 +1918,6 @@ bool wlan_info_init(void)
}
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);

View File

@@ -80,15 +80,11 @@ void extract_ports(const struct tcphdr *tcphdr, const struct udphdr *udphdr, uin
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);
bool extract_dst(const uint8_t *data, size_t len, struct sockaddr* 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(const struct tcphdr *tcp);
bool tcp_synack_segment(const struct tcphdr *tcphdr);
bool tcp_syn_segment(const struct tcphdr *tcphdr);
bool ip_has_df(const struct ip *ip);
bool make_writeable_dir();
bool ensure_file_access(const char *filename);
#ifdef __CYGWIN__
@@ -98,7 +94,7 @@ bool ensure_dir_access(const char *filename);
bool prepare_low_appdata();
bool win_sandbox(void);
bool win_dark_init(const struct str_list_head *ssid_filter, const struct str_list_head *nlm_filter);
bool win_dark_deinit(void);
void win_dark_deinit(void);
bool logical_net_filter_present(void);
bool logical_net_filter_match(void);
bool nlm_list(bool bAll);
@@ -162,6 +158,8 @@ struct dissect
size_t len_payload;
};
void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis);
void reverse_ip(struct ip *ip, struct ip6_hdr *ip6);
void reverse_tcp(struct tcphdr *tcp);
uint8_t ttl46(const struct ip *ip, const struct ip6_hdr *ip6);
@@ -190,7 +188,6 @@ 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);

File diff suppressed because it is too large Load Diff

View File

@@ -13,8 +13,10 @@
#ifdef __linux__
#define DPI_DESYNC_FWMARK_DEFAULT 0x40000000
#else
#elif defined(SO_USER_COOKIE)
#define DPI_DESYNC_FWMARK_DEFAULT 512
#else
#define DPI_DESYNC_FWMARK_DEFAULT 0
#endif
uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifin, const char *ifout, const uint8_t *data_pkt, size_t len_pkt, uint8_t *mod_pkt, size_t *len_mod_pkt);

View File

@@ -7,7 +7,7 @@
#define BUFMIN 128
#define BUFCHUNK (1024*128)
int z_readfile(FILE *F, char **buf, size_t *size)
int z_readfile(FILE *F, char **buf, size_t *size, size_t extra_alloc)
{
z_stream zs;
int r;
@@ -31,14 +31,19 @@ int z_readfile(FILE *F, char **buf, size_t *size)
r = Z_ERRNO;
goto zerr;
}
if (!zs.avail_in) break;
if (!zs.avail_in)
{
// file is not full
r = Z_DATA_ERROR;
goto zerr;
}
zs.next_in = in;
do
{
if ((bufsize - *size) < BUFMIN)
{
bufsize += BUFCHUNK;
newbuf = *buf ? realloc(*buf, bufsize) : malloc(bufsize);
newbuf = *buf ? realloc(*buf, bufsize + extra_alloc) : malloc(bufsize + extra_alloc);
if (!newbuf)
{
r = Z_MEM_ERROR;
@@ -57,7 +62,7 @@ int z_readfile(FILE *F, char **buf, size_t *size)
if (*size < bufsize)
{
// free extra space
if ((newbuf = realloc(*buf, *size))) *buf = newbuf;
if ((newbuf = realloc(*buf, *size + extra_alloc))) *buf = newbuf;
}
inflateEnd(&zs);

View File

@@ -4,5 +4,5 @@
#include <zlib.h>
#include <stdbool.h>
int z_readfile(FILE *F,char **buf,size_t *size);
int z_readfile(FILE *F, char **buf, size_t *size, size_t extra_alloc);
bool is_gzip(FILE* F);

View File

@@ -12,7 +12,7 @@
#define UNIQ_SORT \
{ \
int i, j, u; \
size_t i, j, u; \
for (i = j = 0; j < ct; i++) \
{ \
u = pu[j++]; \
@@ -367,6 +367,19 @@ void phton32(uint8_t *p, uint32_t v)
p[2] = (uint8_t)(v>>8);
p[3] = (uint8_t)v;
}
uint64_t pntoh48(const uint8_t *p)
{
return ((uint64_t)p[0] << 40) | ((uint64_t)p[1] << 32) | ((uint64_t)p[2] << 24) | ((uint64_t)p[3] << 16) | ((uint64_t)p[4] << 8) | p[5];
}
void phton48(uint8_t *p, uint64_t v)
{
p[0] = (uint8_t)(v>>40);
p[1] = (uint8_t)(v>>32);
p[2] = (uint8_t)(v>>24);
p[3] = (uint8_t)(v>>16);
p[4] = (uint8_t)(v>>8);
p[5] = (uint8_t)v;
}
uint64_t pntoh64(const uint8_t *p)
{
return ((uint64_t)p[0] << 56) | ((uint64_t)p[1] << 48) | ((uint64_t)p[2] << 40) | ((uint64_t)p[3] << 32) | ((uint64_t)p[4] << 24) | ((uint64_t)p[5] << 16) | ((uint64_t)p[6] << 8) | p[7];
@@ -383,6 +396,20 @@ void phton64(uint8_t *p, uint64_t v)
p[7] = (uint8_t)v;
}
uint16_t bswap16(uint16_t u)
{
// __builtin_bswap16 is absent in ancient lexra gcc 4.6
return (u>>8) | ((u&0xFF)<<8);
}
uint32_t bswap24(uint32_t u)
{
return (u>>16) & 0xFF | u & 0xFF00 | (u<<16) & 0xFF0000;
}
uint64_t bswap48(uint64_t u)
{
return ((u & 0xFF0000000000) >> 40) | ((u & 0xFF00000000) >> 24) | ((u & 0xFF000000) >> 8) | ((u & 0xFF0000) << 8) | ((u & 0xFF00) << 24) | ((u & 0xFF) << 40);
}
#define INVALID_HEX_DIGIT ((uint8_t)-1)
static inline uint8_t parse_hex_digit(char c)
@@ -514,7 +541,7 @@ bool pf_is_empty(const port_filter *pf)
bool packet_pos_parse(const char *s, struct packet_pos *pos)
{
if (*s!='n' && *s!='d' && *s!='s' && *s!='b' && *s!='x' && *s!='a') return false;
if (*s!='n' && *s!='d' && *s!='s' && *s!='p' && *s!='b' && *s!='x' && *s!='a') return false;
pos->mode=*s;
if (pos->mode=='x' || pos->mode=='a')
{
@@ -615,42 +642,13 @@ bool set_env_exedir(const char *argv0)
if ((s = strdup(argv0)))
{
if ((d = dirname(s)))
setenv("EXEDIR",s,1);
bOK = !setenv("EXEDIR",d,1);
free(s);
}
return bOK;
}
static void mask_from_preflen6_make(uint8_t plen, struct in6_addr *a)
{
if (plen >= 128)
memset(a->s6_addr,0xFF,16);
else
{
uint8_t n = plen >> 3;
memset(a->s6_addr,0xFF,n);
memset(a->s6_addr+n,0x00,16-n);
a->s6_addr[n] = (uint8_t)(0xFF00 >> (plen & 7));
}
}
struct in6_addr ip6_mask[129];
void mask_from_preflen6_prepare(void)
{
for (int plen=0;plen<=128;plen++) mask_from_preflen6_make(plen, ip6_mask+plen);
}
#if defined(__GNUC__) && !defined(__llvm__)
__attribute__((optimize ("no-strict-aliasing")))
#endif
void ip6_and(const struct in6_addr * restrict a, const struct in6_addr * restrict b, struct in6_addr * restrict result)
{
// int128 requires 16-bit alignment. in struct sockaddr_in6.sin6_addr is 8-byte aligned.
// it causes segfault on x64 arch with latest compiler. it can cause misalign slowdown on other archs
// use 64-bit AND
((uint64_t*)result->s6_addr)[0] = ((uint64_t*)a->s6_addr)[0] & ((uint64_t*)b->s6_addr)[0];
((uint64_t*)result->s6_addr)[1] = ((uint64_t*)a->s6_addr)[1] & ((uint64_t*)b->s6_addr)[1];
}
void str_cidr4(char *s, size_t s_len, const struct cidr4 *cidr)
{

View File

@@ -61,9 +61,15 @@ uint32_t pntoh24(const uint8_t *p);
void phton24(uint8_t *p, uint32_t v);
uint32_t pntoh32(const uint8_t *p);
void phton32(uint8_t *p, uint32_t v);
uint64_t pntoh48(const uint8_t *p);
void phton48(uint8_t *p, uint64_t v);
uint64_t pntoh64(const uint8_t *p);
void phton64(uint8_t *p, uint64_t v);
uint16_t bswap16(uint16_t u);
uint32_t bswap24(uint32_t u);
uint64_t bswap48(uint64_t u);
bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size);
char hex_digit(uint8_t v);
@@ -133,15 +139,3 @@ bool parse_cidr4(char *s, struct cidr4 *cidr);
bool parse_cidr6(char *s, struct cidr6 *cidr);
bool parse_int16(const char *p, int16_t *v);
static inline uint32_t mask_from_preflen(uint32_t preflen)
{
return preflen ? preflen<32 ? ~((1 << (32-preflen)) - 1) : 0xFFFFFFFF : 0;
}
void ip6_and(const struct in6_addr * restrict a, const struct in6_addr * restrict b, struct in6_addr * restrict result);
extern struct in6_addr ip6_mask[129];
void mask_from_preflen6_prepare(void);
static inline const struct in6_addr *mask_from_preflen6(uint8_t preflen)
{
return ip6_mask+preflen;
}

View File

@@ -8,13 +8,8 @@ static bool addpool(hostlist_pool **hostlist, char **s, const char *end, int *ct
{
char *p=*s;
// comment line
if ( *p == '#' || *p == ';' || *p == '/' || *p == '\r' || *p == '\n')
{
// advance until eol
for (; p<end && *p && *p!='\r' && *p != '\n'; p++);
}
else
// comment line ?
if ( *p != '#' && *p != ';' && *p != '/' && *p != '\r' && *p != '\n')
{
// advance until eol lowering all chars
uint32_t flags = 0;
@@ -23,7 +18,7 @@ static bool addpool(hostlist_pool **hostlist, char **s, const char *end, int *ct
p = ++(*s);
flags |= HOSTLIST_POOL_FLAG_STRICT_MATCH;
}
for (; p<end && *p && *p!='\r' && *p != '\n'; p++) *p=tolower(*p);
for (; p<end && *p && *p!=' ' && *p!='\t' && *p!='\r' && *p != '\n'; p++) *p=tolower(*p);
if (!HostlistPoolAddStrLen(hostlist, *s, p-*s, flags))
{
HostlistPoolDestroy(hostlist);
@@ -32,6 +27,8 @@ static bool addpool(hostlist_pool **hostlist, char **s, const char *end, int *ct
}
if (ct) (*ct)++;
}
// skip remaining non-eol chars
for (; p<end && *p && *p!='\r' && *p != '\n'; p++);
// advance to the next line
for (; p<end && (!*p || *p=='\r' || *p=='\n') ; p++);
*s = p;
@@ -61,7 +58,7 @@ bool AppendHostList(hostlist_pool **hostlist, const char *filename)
if (is_gzip(F))
{
r = z_readfile(F,&zbuf,&zsize);
r = z_readfile(F,&zbuf,&zsize,0);
fclose(F);
if (r==Z_OK)
{
@@ -82,7 +79,7 @@ bool AppendHostList(hostlist_pool **hostlist, const char *filename)
}
else
{
DLOG_ERR("zlib decompression failed : result %d\n",r);
DLOG_ERR("zlib decompression failed : result %d\n", r);
return false;
}
}

View File

@@ -4,7 +4,6 @@
#include "helpers.h"
// inplace tolower() and add to pool
static bool addpool(ipset *ips, char **s, const char *end, int *ct)
{
char *p, cidr[128];
@@ -12,8 +11,7 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
struct cidr4 c4;
struct cidr6 c6;
// advance until eol
for (p=*s; p<end && *p && *p!='\r' && *p != '\n'; p++);
for (p=*s; p<end && *p && *p!=' ' && *p!='\t' && *p!='\r' && *p != '\n'; p++);
// comment line
if (!(**s == '#' || **s == ';' || **s == '/' || **s == '\r' || **s == '\n' ))
@@ -22,7 +20,6 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
if (l>=sizeof(cidr)) l=sizeof(cidr)-1;
memcpy(cidr,*s,l);
cidr[l]=0;
rtrim(cidr);
if (parse_cidr4(cidr,&c4))
{
@@ -46,6 +43,8 @@ static bool addpool(ipset *ips, char **s, const char *end, int *ct)
DLOG_ERR("bad ip or subnet : %s\n",cidr);
}
// skip remaining non-eol chars
for (; p<end && *p && *p!='\r' && *p != '\n'; p++);
// advance to the next line
for (; p<end && (!*p || *p=='\r' || *p=='\n') ; p++);
*s = p;
@@ -76,7 +75,7 @@ static bool AppendIpset(ipset *ips, const char *filename)
if (is_gzip(F))
{
r = z_readfile(F,&zbuf,&zsize);
r = z_readfile(F,&zbuf,&zsize,0);
fclose(F);
if (r==Z_OK)
{

1997
nfq2/lua.c

File diff suppressed because it is too large Load Diff

View File

@@ -34,6 +34,7 @@
#endif
// pushing and not popping inside luacall cause memory leak
// these macros ensure correct stack position or throw error if not
#define LUA_STACK_GUARD_ENTER(L) int _lsg=lua_gettop(L);
#define LUA_STACK_GUARD_LEAVE(L,N) if ((_lsg+N)!=lua_gettop(L)) luaL_error(L,"stack guard failure");
#define LUA_STACK_GUARD_RETURN(L,N) LUA_STACK_GUARD_LEAVE(L,N); return N;
@@ -56,47 +57,49 @@ int lua_absindex(lua_State *L, int idx);
// push - create object and push to the stack
// pushf - create object and set it as a named field of a table already present on the stack
// pushi - create object and set it as a index field of a table already present on the stack
void lua_pushf_nil(const char *field);
void lua_pushi_nil(lua_Integer idx);
void lua_pushf_bool(const char *field, bool b);
void lua_pushi_bool(lua_Integer idx, bool b);
void lua_pushf_str(const char *field, const char *str);
void lua_pushi_str(lua_Integer idx, const char *str);
void lua_pushf_lstr(const char *field, const char *str, size_t len);
void lua_pushi_lstr(lua_Integer idx, const char *str, size_t len);
void lua_pushf_int(const char *field, lua_Integer v);
void lua_pushi_int(lua_Integer idx, lua_Integer v);
void lua_pushf_lint(const char *field, int64_t v);
void lua_pushi_lint(lua_Integer idx, int64_t v);
void lua_push_raw(const void *v, size_t l);
void lua_pushf_raw(const char *field, const void *v, size_t l);
void lua_pushi_raw(lua_Integer idx, const void *v, size_t l);
void lua_pushf_reg(const char *field, int ref);
void lua_pushf_lud(const char *field, void *p);
void lua_pushf_table(const char *field);
void lua_pushi_table(lua_Integer idx);
void lua_pushf_nil(lua_State *L, const char *field);
void lua_pushi_nil(lua_State *L, lua_Integer idx);
void lua_pushf_bool(lua_State *L, const char *field, bool b);
void lua_pushi_bool(lua_State *L, lua_Integer idx, bool b);
void lua_pushf_str(lua_State *L, const char *field, const char *str);
void lua_pushi_str(lua_State *L, lua_Integer idx, const char *str);
void lua_pushf_lstr(lua_State *L, const char *field, const char *str, size_t len);
void lua_pushi_lstr(lua_State *L, lua_Integer idx, const char *str, size_t len);
void lua_pushf_int(lua_State *L, const char *field, lua_Integer v);
void lua_pushi_int(lua_State *L, lua_Integer idx, lua_Integer v);
void lua_pushf_lint(lua_State *L, const char *field, int64_t v);
void lua_pushi_lint(lua_State *L, lua_Integer idx, int64_t v);
void lua_pushf_number(lua_State *L, const char *field, lua_Number v);
void lua_pushi_number(lua_State *L, lua_Integer idx, lua_Number v);
void lua_push_raw(lua_State *L, const void *v, size_t l);
void lua_pushf_raw(lua_State *L, const char *field, const void *v, size_t l);
void lua_pushi_raw(lua_State *L, lua_Integer idx, const void *v, size_t l);
void lua_pushf_reg(lua_State *L, const char *field, int ref);
void lua_pushf_lud(lua_State *L, const char *field, void *p);
void lua_pushf_table(lua_State *L, const char *field);
void lua_pushi_table(lua_State *L, lua_Integer idx);
void lua_push_blob(int idx_desync, const char *blob);
void lua_pushf_blob(int idx_desync, const char *field, const char *blob);
void lua_push_blob(lua_State *L, int idx_desync, const char *blob);
void lua_pushf_blob(lua_State *L, int idx_desync, const char *field, const char *blob);
void lua_pushf_tcphdr_options(const struct tcphdr *tcp, size_t len);
void lua_pushf_tcphdr(const struct tcphdr *tcp, size_t len);
void lua_pushf_udphdr(const struct udphdr *udp, size_t len);
void lua_pushf_iphdr(const struct ip *ip, size_t len);
void lua_pushf_ip6hdr(const struct ip6_hdr *ip6, size_t len);
void lua_push_dissect(const struct dissect *dis);
void lua_pushf_dissect(const struct dissect *dis);
void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_position *pos);
void lua_pushf_args(const struct str2_list_head *args, int idx_desync);
void lua_pushf_pos(const char *name, const struct packet_pos *pos);
void lua_pushf_range(const char *name, const struct packet_range *range);
void lua_pushf_global(const char *field, const char *global);
void lua_pushf_tcphdr_options(lua_State *L, const struct tcphdr *tcp, size_t len);
void lua_pushf_tcphdr(lua_State *L, const struct tcphdr *tcp, size_t len);
void lua_pushf_udphdr(lua_State *L, const struct udphdr *udp, size_t len);
void lua_pushf_iphdr(lua_State *L, const struct ip *ip, size_t len);
void lua_pushf_ip6hdr(lua_State *L, const struct ip6_hdr *ip6, size_t len);
void lua_push_dissect(lua_State *L, const struct dissect *dis);
void lua_pushf_dissect(lua_State *L, const struct dissect *dis);
void lua_pushf_ctrack(lua_State *L, const t_ctrack *ctrack, const t_ctrack_positions *tpos, bool bIncoming);
void lua_pushf_args(lua_State *L, const struct str2_list_head *args, int idx_desync, bool subst_prefix);
void lua_pushf_pos(lua_State *L, const char *name, const struct packet_pos *pos);
void lua_pushf_range(lua_State *L, const char *name, const struct packet_range *range);
void lua_pushf_global(lua_State *L, const char *field, const char *global);
bool lua_reconstruct_ip6hdr(int idx, struct ip6_hdr *ip6, size_t *len, uint8_t last_proto, bool preserve_next);
bool lua_reconstruct_iphdr(int idx, struct ip *ip, size_t *len);
bool lua_reconstruct_tcphdr(int idx, struct tcphdr *tcp, size_t *len);
bool lua_reconstruct_udphdr(int idx, struct udphdr *udp);
bool lua_reconstruct_dissect(int idx, uint8_t *buf, size_t *len, bool badsum, bool ip6_preserve_next);
bool lua_reconstruct_ip6hdr(lua_State *L, int idx, struct ip6_hdr *ip6, size_t *len, uint8_t last_proto, bool preserve_next);
bool lua_reconstruct_iphdr(lua_State *L, int idx, struct ip *ip, size_t *len);
bool lua_reconstruct_tcphdr(lua_State *L, int idx, struct tcphdr *tcp, size_t *len);
bool lua_reconstruct_udphdr(lua_State *L, int idx, struct udphdr *udp);
bool lua_reconstruct_dissect(lua_State *L, int idx, uint8_t *buf, size_t *len, bool badsum, bool ip6_preserve_next);
typedef struct {
unsigned int func_n;
@@ -104,7 +107,8 @@ typedef struct {
const struct desync_profile *dp;
const struct dissect *dis;
t_ctrack *ctrack;
bool incoming,cancel;
bool incoming, cancel;
bool valid;
} t_lua_desync_context;
bool lua_instance_cutoff_check(const t_lua_desync_context *ctx, bool bIn);
bool lua_instance_cutoff_check(lua_State *L, const t_lua_desync_context *ctx, bool bIn);

View File

@@ -51,14 +51,13 @@
#define MAX_CONFIG_FILE_SIZE 16384
struct params_s params;
static bool bReload = false;
#ifdef __CYGWIN__
static volatile sig_atomic_t bReload = false;
bool bQuit = false;
#endif
static void onhup(int sig)
{
printf("HUP received ! Lists will be reloaded.\n");
const char *msg = "HUP received ! Lists will be reloaded.\n";
size_t wr = write(1, msg, strlen(msg));
bReload = true;
}
static void ReloadCheck()
@@ -101,12 +100,37 @@ static void onusr2(int sig)
ipcachePrint(&params.ipcache);
printf("\n");
}
static void onint(int sig)
{
const char *msg = "INT received !\n";
size_t wr = write(1, msg, strlen(msg));
bQuit = true;
}
static void onterm(int sig)
{
const char *msg = "TERM received !\n";
size_t wr = write(1, msg, strlen(msg));
bQuit = true;
}
static void pre_desync(void)
{
signal(SIGHUP, onhup);
signal(SIGUSR1, onusr1);
signal(SIGUSR2, onusr2);
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = NULL;
sa.sa_flags = 0;
sa.sa_handler = onhup;
sigaction(SIGHUP, &sa, NULL);
sa.sa_handler = onusr1;
sigaction(SIGUSR1, &sa, NULL);
sa.sa_handler = onusr2;
sigaction(SIGUSR2, &sa, NULL);
sa.sa_handler = onint;
sigaction(SIGINT, &sa, NULL);
sa.sa_handler = onterm;
sigaction(SIGTERM, &sa, NULL);
}
@@ -155,13 +179,14 @@ static int nfq_cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_da
uint8_t *data;
uint32_t ifidx_out, ifidx_in;
char ifout[IFNAMSIZ], ifin[IFNAMSIZ];
uint8_t mod[RECONSTRUCT_MAX_SIZE];
size_t modlen;
uint32_t mark;
uint8_t mod[RECONSTRUCT_MAX_SIZE];
ph = nfq_get_msg_packet_hdr(nfa);
id = ph ? ntohl(ph->packet_id) : 0;
uint32_t mark = nfq_get_nfmark(nfa);
mark = nfq_get_nfmark(nfa);
ilen = nfq_get_payload(nfa, &data);
ifidx_out = nfq_get_outdev(nfa);
@@ -281,12 +306,12 @@ static void notify_ready(void)
static int nfq_main(void)
{
uint8_t buf[RECONSTRUCT_MAX_SIZE] __attribute__((aligned));
struct nfq_handle *h = NULL;
struct nfq_q_handle *qh = NULL;
int res, fd, e;
ssize_t rd;
FILE *Fpid = NULL;
uint8_t buf[RECONSTRUCT_MAX_SIZE] __attribute__((aligned));
if (*params.pidfile && !(Fpid = fopen(params.pidfile, "w")))
{
@@ -347,6 +372,7 @@ static int nfq_main(void)
{
while ((rd = recv(fd, buf, sizeof(buf), 0)) >= 0)
{
if (bQuit) goto quit;
ReloadCheck();
lua_do_gc();
#ifdef HAS_FILTER_SSID
@@ -362,6 +388,11 @@ static int nfq_main(void)
else
DLOG("recv from nfq returned 0 !\n");
}
if (errno==EINTR)
{
if (bQuit) goto quit;
continue;
}
e = errno;
DLOG_ERR("recv: recv=%zd errno %d\n", rd, e);
errno = e;
@@ -369,6 +400,7 @@ static int nfq_main(void)
// do not fail on ENOBUFS
} while (e == ENOBUFS);
exok:
res=0;
ex:
nfq_deinit(&h, &qh);
@@ -376,18 +408,21 @@ ex:
#ifdef HAS_FILTER_SSID
wlan_info_deinit();
#endif
rawsend_cleanup();
return res;
err:
if (Fpid) fclose(Fpid);
res=1;
goto ex;
quit:
DLOG_CONDUP("quit requested\n");
goto exok;
}
#elif defined(BSD)
static int dvt_main(void)
{
uint8_t buf[RECONSTRUCT_MAX_SIZE] __attribute__((aligned));
struct sockaddr_storage sa_from;
int fd[2] = { -1,-1 }; // 4,6
int i, r, res = 1, fdct = 1, fdmax;
@@ -396,6 +431,9 @@ static int dvt_main(void)
ssize_t rd, wr;
fd_set fdset;
FILE *Fpid = NULL;
struct sockaddr_in bp4;
struct sockaddr_in6 bp6;
uint8_t buf[RECONSTRUCT_MAX_SIZE] __attribute__((aligned));
if (*params.pidfile && !(Fpid = fopen(params.pidfile, "w")))
{
@@ -403,49 +441,42 @@ static int dvt_main(void)
return 1;
}
bp4.sin_family = AF_INET;
bp4.sin_port = htons(params.port);
bp4.sin_addr.s_addr = INADDR_ANY;
DLOG_CONDUP("creating divert4 socket\n");
fd[0] = socket_divert(AF_INET);
if (fd[0] == -1) {
DLOG_PERROR("socket (DIVERT4)");
goto exiterr;
}
DLOG_CONDUP("binding divert4 socket\n");
if (bind(fd[0], (struct sockaddr*)&bp4, sizeof(bp4)) < 0)
{
struct sockaddr_in bp4;
bp4.sin_family = AF_INET;
bp4.sin_port = htons(params.port);
bp4.sin_addr.s_addr = INADDR_ANY;
DLOG_CONDUP("creating divert4 socket\n");
fd[0] = socket_divert(AF_INET);
if (fd[0] == -1) {
DLOG_PERROR("socket (DIVERT4)");
goto exiterr;
}
DLOG_CONDUP("binding divert4 socket\n");
if (bind(fd[0], (struct sockaddr*)&bp4, sizeof(bp4)) < 0)
{
DLOG_PERROR("bind (DIVERT4)");
goto exiterr;
}
DLOG_PERROR("bind (DIVERT4)");
goto exiterr;
}
#ifdef __OpenBSD__
{
// in OpenBSD must use separate divert sockets for ipv4 and ipv6
struct sockaddr_in6 bp6;
memset(&bp6, 0, sizeof(bp6));
bp6.sin6_family = AF_INET6;
bp6.sin6_port = htons(params.port);
// in OpenBSD must use separate divert sockets for ipv4 and ipv6
memset(&bp6, 0, sizeof(bp6));
bp6.sin6_family = AF_INET6;
bp6.sin6_port = htons(params.port);
DLOG_CONDUP("creating divert6 socket\n");
fd[1] = socket_divert(AF_INET6);
if (fd[1] == -1) {
DLOG_PERROR("socket (DIVERT6)");
goto exiterr;
}
DLOG_CONDUP("binding divert6 socket\n");
if (bind(fd[1], (struct sockaddr*)&bp6, sizeof(bp6)) < 0)
{
DLOG_PERROR("bind (DIVERT6)");
goto exiterr;
}
fdct++;
DLOG_CONDUP("creating divert6 socket\n");
fd[1] = socket_divert(AF_INET6);
if (fd[1] == -1) {
DLOG_PERROR("socket (DIVERT6)");
goto exiterr;
}
DLOG_CONDUP("binding divert6 socket\n");
if (bind(fd[1], (struct sockaddr*)&bp6, sizeof(bp6)) < 0)
{
DLOG_PERROR("bind (DIVERT6)");
goto exiterr;
}
fdct++;
#endif
fdmax = (fd[0] > fd[1] ? fd[0] : fd[1]) + 1;
@@ -485,13 +516,14 @@ static int dvt_main(void)
FD_ZERO(&fdset);
for (i = 0; i < fdct; i++) FD_SET(fd[i], &fdset);
r = select(fdmax, &fdset, NULL, NULL, NULL);
if (bQuit)
{
DLOG_CONDUP("quit requested\n");
goto exitok;
}
if (r == -1)
{
if (errno == EINTR)
{
// a signal received
continue;
}
if (errno == EINTR) continue;
DLOG_PERROR("select");
goto exiterr;
}
@@ -538,7 +570,7 @@ static int dvt_main(void)
DLOG("\npacket: id=%u len=%zu ifin=%s ifout=%s\n", id, len, ifin, ifout);
modlen = sizeof(buf);
verdict = processPacketData(&mark, NULL, NULL, buf, len, buf, &modlen);
verdict = processPacketData(&mark, ifin, ifout, buf, len, buf, &modlen);
switch (verdict & VERDICT_MASK)
{
case VERDICT_PASS:
@@ -569,12 +601,14 @@ static int dvt_main(void)
}
}
exitok:
res = 0;
exiterr:
if (Fpid) fclose(Fpid);
if (fd[0] != -1) close(fd[0]);
if (fd[1] != -1) close(fd[1]);
lua_shutdown();
rawsend_cleanup();
return res;
}
@@ -587,11 +621,11 @@ static int win_main()
unsigned int id;
uint8_t verdict;
bool bOutbound;
uint8_t packet[RECONSTRUCT_MAX_SIZE];
uint32_t mark;
WINDIVERT_ADDRESS wa;
char ifname[IFNAMSIZ];
int res=0;
uint8_t packet[RECONSTRUCT_MAX_SIZE];
if (params.daemon) daemonize();
@@ -618,7 +652,7 @@ static int win_main()
{
if (bQuit)
{
DLOG("QUIT requested\n");
DLOG("quit requested\n");
goto ex;
}
usleep(500000);
@@ -630,6 +664,7 @@ static int win_main()
{
res=w_win32_error; goto ex;
}
if (!win_sandbox())
{
res=w_win32_error;
@@ -637,7 +672,6 @@ static int win_main()
goto ex;
}
// init LUA only here because of possible sandbox. no LUA code with high privs
if (!params.L && !lua_init())
{
@@ -659,12 +693,11 @@ static int win_main()
else if (errno == ENODEV)
{
DLOG_CONDUP("logical network disappeared. deinitializing windivert.\n");
rawsend_cleanup();
break;
}
else if (errno == EINTR)
{
DLOG("QUIT requested\n");
DLOG("quit requested\n");
goto ex;
}
DLOG_ERR("windivert: recv failed. errno %d\n", errno);
@@ -683,11 +716,6 @@ static int win_main()
DLOG("windivert: passing impostor packet\n");
verdict = VERDICT_PASS;
}
else if (wa.Loopback)
{
DLOG("windivert: passing loopback packet\n");
verdict = VERDICT_PASS;
}
else
{
mark = 0;
@@ -715,6 +743,7 @@ static int win_main()
ex:
win_dark_deinit();
lua_shutdown();
rawsend_cleanup();
return res;
}
@@ -726,6 +755,7 @@ ex:
static void exit_clean(int code)
{
cleanup_params(&params);
exit(code);
}
@@ -1256,7 +1286,7 @@ static bool wf_make_pf(char *opt, const char *l4, const char *portname, char *bu
// HTTP/1.? 30(2|7)
#define DIVERT_HTTP_REDIRECT "tcp.PayloadLength>=12 and tcp.Payload32[0]==0x48545450 and tcp.Payload16[2]==0x2F31 and tcp.Payload[6]==0x2E and tcp.Payload16[4]==0x2033 and tcp.Payload[10]==0x30 and (tcp.Payload[11]==0x32 or tcp.Payload[11]==0x37)"
#define DIVERT_PROLOG "!impostor and !loopback"
#define DIVERT_PROLOG "!impostor"
static bool wf_make_filter(
char *wf, size_t len,
@@ -1267,12 +1297,14 @@ static bool wf_make_filter(
const char *pf_tcp_src_in, const char *pf_tcp_dst_in,
const char *pf_udp_src_in, const char *pf_udp_dst_out,
const struct str_list_head *wf_raw_part,
bool bFilterOutLAN)
bool bFilterOutLAN, bool bFilterOutLoopback)
{
struct str_list *wfpart;
bool bHaveTCP = *pf_tcp_src_in || *pf_tcp_dst_out;
snprintf(wf, len, "%s", DIVERT_PROLOG);
if (bFilterOutLoopback)
snprintf(wf + strlen(wf), len - strlen(wf), " and !loopback");
if (IfIdx)
snprintf(wf + strlen(wf), len - strlen(wf), " and ifIdx=%u and subIfIdx=%u", IfIdx, SubIfIdx);
if (ipv4 ^ ipv6)
@@ -1339,7 +1371,7 @@ static void exithelp(void)
*all_payloads=0;
for (t_l7payload pl=0 ; pl<L7P_LAST; pl++)
{
if (pl) strncat(all_payloads, " ", sizeof(all_payloads)-1-1);
if (pl) strncat(all_payloads, " ", sizeof(all_payloads)-strlen(all_payloads)-1);
strncat(all_payloads, l7payload_str(pl), sizeof(all_payloads)-strlen(all_payloads)-1);
}
*all_protos=0;
@@ -1381,10 +1413,11 @@ static void exithelp(void)
#endif
" --ctrack-timeouts=S:E:F[:U]\t\t\t\t; internal conntrack timeouts for TCP SYN, ESTABLISHED, FIN stages, UDP timeout. default %u:%u:%u:%u\n"
" --ctrack-disable=[0|1]\t\t\t\t\t; 1 or no argument disables conntrack\n"
" --payload-disable=[type[,type]]\t\t\t; do not discover these payload types. for available payload types see '--payload'. disable all if no argument.\n"
" --server=[0|1]\t\t\t\t\t\t; change multiple aspects of src/dst ip/port handling for incoming connections\n"
" --ipcache-lifetime=<int>\t\t\t\t; time in seconds to keep cached hop count and domain name (default %u). 0 = no expiration\n"
" --ipcache-hostname=[0|1]\t\t\t\t; 1 or no argument enables ip->hostname caching\n"
" --reasm-disable=[proto[,proto]]\t\t\t; disable reasm for these L7 payloads : tls_client_hello quic_initial . if no argument - disable all reasm.\n"
" --reasm-disable=[type[,type]]\t\t\t\t; disable reasm for these L7 payloads : tls_client_hello quic_initial . if no argument - disable all reasm.\n"
#ifdef __CYGWIN__
"\nWINDIVERT FILTER:\n"
" --wf-iface=<int>[.<int>]\t\t\t\t; numeric network interface and subinterface indexes\n"
@@ -1396,6 +1429,7 @@ static void exithelp(void)
" --wf-tcp-empty=[0|1]\t\t\t\t\t; enable processing of empty tcp packets without flags SYN,RST,FIN (default : 0)\n"
" --wf-raw-part=<filter>|@<filename>\t\t\t; partial raw windivert filter string or filename\n"
" --wf-filter-lan=0|1\t\t\t\t\t; add excluding filter for non-global IP (default : 1)\n"
" --wf-filter-loopback=0|1\t\t\t\t; add excluding filter for loopback (default : 1)\n"
" --wf-raw=<filter>|@<filename>\t\t\t\t; full raw windivert filter string or filename. replaces --wf-tcp,--wf-udp,--wf-raw-part\n"
" --wf-save=<filename>\t\t\t\t\t; save windivert filter string to a file and exit\n"
"\nLOGICAL NETWORK FILTER:\n"
@@ -1406,7 +1440,7 @@ static void exithelp(void)
"\nDESYNC ENGINE INIT:\n"
" --writeable[=<dir_name>]\t\t\t\t; create writeable dir for LUA scripts and pass it in WRITEABLE env variable (only one dir possible)\n"
" --blob=<item_name>:[+ofs]@<filename>|0xHEX\t\t; load blob to LUA var <item_name>\n"
" --lua-init=@<filename>|<lua_text>\t\t\t; load LUA program from a file or string. if multiple parameters present order of execution is preserved.\n"
" --lua-init=@<filename>|<lua_text>\t\t\t; load LUA program from a file or string. if multiple parameters present order of execution is preserved. gzipped files are supported.\n"
" --lua-gc=<int>\t\t\t\t\t\t; forced garbage collection every N sec. default %u sec. triggers only when a packet arrives. 0 = disable.\n"
"\nMULTI-STRATEGY:\n"
" --new\t\t\t\t\t\t\t; begin new profile\n"
@@ -1434,11 +1468,16 @@ static void exithelp(void)
" --hostlist-auto-fail-threshold=<int>\t\t\t; how many failed attempts cause hostname to be added to auto hostlist (default : %d)\n"
" --hostlist-auto-fail-time=<int>\t\t\t; all failed attemps must be within these seconds (default : %d)\n"
" --hostlist-auto-retrans-threshold=<int>\t\t; how many request retransmissions cause attempt to fail (default : %d)\n"
" --hostlist-auto-retrans-maxseq=<int>\t\t\t; count retransmissions only within this relative sequence (default : %u)\n"
" --hostlist-auto-retrans-reset=[0|1]\t\t\t; send RST to retransmitter to break long wait (default: 1)\n"
" --hostlist-auto-incoming-maxseq=<int>\t\t\t; treat tcp connection as successful if incoming relative sequence exceedes this threshold (default : %u)\n"
" --hostlist-auto-udp-out=<int>\t\t\t\t; udp failure condition : sent at least `udp_out` packets (default : %u)\n"
" --hostlist-auto-udp-in=<int>\t\t\t\t; udp failure condition : received not more than `udp_in` packets (default : %u)\n"
" --hostlist-auto-debug=<logfile>\t\t\t; debug auto hostlist positives (global parameter)\n"
"\nLUA PACKET PASS MODE:\n"
" --payload=type[,type]\t\t\t\t\t; set payload types following LUA functions should process : %s\n"
" --out-range=[(n|a|d|s)<int>](-|<)[(n|a|d|s)<int>]\t; set outgoing packet range for following LUA functions. '-' - include end pos, '<' - not include. prefix meaning : n - packet number, d - data packet number, s - relative sequence, b - byte count, x - never, a - always\n"
" --in-range=[(n|a|d|s)<int>](-|<)[(n|a|d|s)<int>]\t; set incoming packet range for following LUA functions. '-' - include end pos, '<' - not include. prefix meaning : n - packet number, d - data packet number, s - relative sequence, b - byte count, x - never, a - always\n"
" --out-range=[(n|a|d|s|p)<int>](-|<)[(n|a|d|s|p)<int>]\t; set outgoing packet range for following LUA functions. '-' - include end pos, '<' - not include. prefix meaning : n - packet number, d - data packet number, s - relative sequence, p - data position relative sequence, b - byte count, x - never, a - always\n"
" --in-range=[(n|a|d|s|p)<int>](-|<)[(n|a|d|s|p)<int>]\t; set incoming packet range for following LUA functions. '-' - include end pos, '<' - not include. prefix meaning : n - packet number, d - data packet number, s - relative sequence, p - data position relative sequence, b - byte count, x - never, a - always\n"
"\nLUA DESYNC ACTION:\n"
" --lua-desync=<functon>[:param1=val1[:param2=val2]]\t; call LUA function when packet received\n",
#if defined(__linux__) || defined(SO_USER_COOKIE)
@@ -1448,7 +1487,10 @@ static void exithelp(void)
IPCACHE_LIFETIME,
LUA_GC_INTERVAL,
all_protos,
HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT, HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT,
HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT,
HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT,
HOSTLIST_AUTO_RETRANS_MAXSEQ, HOSTLIST_AUTO_INCOMING_MAXSEQ,
HOSTLIST_AUTO_UDP_OUT, HOSTLIST_AUTO_UDP_IN,
all_payloads
);
exit(1);
@@ -1486,10 +1528,6 @@ void config_from_file(const char *filename)
}
#endif
static void check_dp(const struct desync_profile *dp)
{
}
static void ApplyDefaultBlobs(struct blob_collection_head *blobs)
{
load_const_blob_to_collection("fake_default_tls",fake_tls_clienthello_default,sizeof(fake_tls_clienthello_default),blobs,BLOB_EXTRA_BYTES);
@@ -1521,6 +1559,7 @@ enum opt_indices {
#endif
IDX_CTRACK_TIMEOUTS,
IDX_CTRACK_DISABLE,
IDX_PAYLOAD_DISABLE,
IDX_SERVER,
IDX_IPCACHE_LIFETIME,
IDX_IPCACHE_HOSTNAME,
@@ -1545,6 +1584,11 @@ enum opt_indices {
IDX_HOSTLIST_AUTO_FAIL_THRESHOLD,
IDX_HOSTLIST_AUTO_FAIL_TIME,
IDX_HOSTLIST_AUTO_RETRANS_THRESHOLD,
IDX_HOSTLIST_AUTO_RETRANS_MAXSEQ,
IDX_HOSTLIST_AUTO_RETRANS_RESET,
IDX_HOSTLIST_AUTO_INCOMING_MAXSEQ,
IDX_HOSTLIST_AUTO_UDP_IN,
IDX_HOSTLIST_AUTO_UDP_OUT,
IDX_HOSTLIST_AUTO_DEBUG,
IDX_NEW,
IDX_SKIP,
@@ -1580,6 +1624,7 @@ enum opt_indices {
IDX_WF_RAW,
IDX_WF_RAW_PART,
IDX_WF_FILTER_LAN,
IDX_WF_FILTER_LOOPBACK,
IDX_WF_SAVE,
IDX_SSID_FILTER,
IDX_NLM_FILTER,
@@ -1608,6 +1653,7 @@ static const struct option long_options[] = {
#endif
[IDX_CTRACK_TIMEOUTS] = {"ctrack-timeouts", required_argument, 0, 0},
[IDX_CTRACK_DISABLE] = {"ctrack-disable", optional_argument, 0, 0},
[IDX_PAYLOAD_DISABLE] = {"payload-disable", optional_argument, 0, 0},
[IDX_SERVER] = {"server", optional_argument, 0, 0},
[IDX_IPCACHE_LIFETIME] = {"ipcache-lifetime", required_argument, 0, 0},
[IDX_IPCACHE_HOSTNAME] = {"ipcache-hostname", optional_argument, 0, 0},
@@ -1629,6 +1675,11 @@ static const struct option long_options[] = {
[IDX_HOSTLIST_AUTO_FAIL_THRESHOLD] = {"hostlist-auto-fail-threshold", required_argument, 0, 0},
[IDX_HOSTLIST_AUTO_FAIL_TIME] = {"hostlist-auto-fail-time", required_argument, 0, 0},
[IDX_HOSTLIST_AUTO_RETRANS_THRESHOLD] = {"hostlist-auto-retrans-threshold", required_argument, 0, 0},
[IDX_HOSTLIST_AUTO_RETRANS_MAXSEQ] = {"hostlist-auto-retrans-maxseq", required_argument, 0, 0},
[IDX_HOSTLIST_AUTO_RETRANS_RESET] = {"hostlist-auto-retrans-reset", optional_argument, 0, 0},
[IDX_HOSTLIST_AUTO_INCOMING_MAXSEQ] = {"hostlist-auto-incoming-maxseq", required_argument, 0, 0},
[IDX_HOSTLIST_AUTO_UDP_IN] = {"hostlist-auto-udp-in", required_argument, 0, 0},
[IDX_HOSTLIST_AUTO_UDP_OUT] = {"hostlist-auto-udp-out", required_argument, 0, 0},
[IDX_HOSTLIST_AUTO_DEBUG] = {"hostlist-auto-debug", required_argument, 0, 0},
[IDX_NEW] = {"new", no_argument, 0, 0},
[IDX_SKIP] = {"skip", no_argument, 0, 0},
@@ -1664,6 +1715,7 @@ static const struct option long_options[] = {
[IDX_WF_RAW] = {"wf-raw", required_argument, 0, 0},
[IDX_WF_RAW_PART] = {"wf-raw-part", required_argument, 0, 0},
[IDX_WF_FILTER_LAN] = {"wf-filter-lan", required_argument, 0, 0},
[IDX_WF_FILTER_LOOPBACK] = {"wf-filter-loopback", required_argument, 0, 0},
[IDX_WF_SAVE] = {"wf-save", required_argument, 0, 0},
[IDX_SSID_FILTER] = {"ssid-filter", required_argument, 0, 0},
[IDX_NLM_FILTER] = {"nlm-filter", required_argument, 0, 0},
@@ -1707,7 +1759,7 @@ int main(int argc, char **argv)
struct packet_range range_in = PACKET_RANGE_NEVER, range_out = PACKET_RANGE_ALWAYS;
#ifdef __CYGWIN__
char wf_save_file[256]="";
bool wf_ipv4 = true, wf_ipv6 = true, wf_filter_lan = true, wf_tcp_empty = false;
bool wf_ipv4 = true, wf_ipv6 = true, wf_filter_lan = true, wf_filter_loopback = true, wf_tcp_empty = false;
unsigned int IfIdx = 0, SubIfIdx = 0;
unsigned int hash_wf_tcp_in = 0, hash_wf_udp_in = 0, hash_wf_tcp_out = 0, hash_wf_udp_out = 0, hash_wf_raw = 0, hash_wf_raw_part = 0, hash_ssid_filter = 0, hash_nlm_filter = 0;
#endif
@@ -1716,7 +1768,6 @@ int main(int argc, char **argv)
srandom(time(NULL));
aes_init_keygen_tables(); // required for aes
mask_from_preflen6_prepare();
set_env_exedir(argv[0]);
set_console_io_buffering();
#ifdef __CYGWIN__
@@ -1797,6 +1848,7 @@ int main(int argc, char **argv)
fprintf(stderr, "cannot create %s\n", params.debug_logfile);
exit_clean(1);
}
fclose(F);
params.debug = true;
params.debug_target = LOG_TARGET_FILE;
}
@@ -1931,6 +1983,18 @@ int main(int argc, char **argv)
case IDX_IPCACHE_HOSTNAME:
params.cache_hostname = !optarg || atoi(optarg);
break;
case IDX_PAYLOAD_DISABLE:
if (optarg)
{
if (!parse_l7p_list(optarg, &params.payload_disable))
{
DLOG_ERR("Invalid payload filter : %s\n", optarg);
exit_clean(1);
}
}
else
params.payload_disable = L7P_ALL;
break;
case IDX_REASM_DISABLE:
if (optarg)
{
@@ -1941,7 +2005,7 @@ int main(int argc, char **argv)
}
}
else
params.reasm_payload_disable = 0xFFFFFFFFFFFFFFFF;
params.reasm_payload_disable = L7P_ALL;
break;
#if defined(__linux__)
case IDX_FWMARK:
@@ -2077,6 +2141,21 @@ int main(int argc, char **argv)
exit_clean(1);
}
break;
case IDX_HOSTLIST_AUTO_RETRANS_MAXSEQ:
dp->hostlist_auto_retrans_maxseq = (uint32_t)atoi(optarg);
break;
case IDX_HOSTLIST_AUTO_INCOMING_MAXSEQ:
dp->hostlist_auto_incoming_maxseq = (uint32_t)atoi(optarg);
break;
case IDX_HOSTLIST_AUTO_RETRANS_RESET:
dp->hostlist_auto_retrans_reset = !optarg || !!atoi(optarg);
break;
case IDX_HOSTLIST_AUTO_UDP_OUT:
dp->hostlist_auto_udp_out = atoi(optarg);
break;
case IDX_HOSTLIST_AUTO_UDP_IN:
dp->hostlist_auto_udp_in = atoi(optarg);
break;
case IDX_HOSTLIST_AUTO_DEBUG:
{
FILE *F = fopen(optarg, "a+t");
@@ -2101,7 +2180,6 @@ int main(int argc, char **argv)
}
else
{
check_dp(dp);
if (bTemplate)
{
if (dp->name && dp_list_search_name(&params.desync_templates, dp->name))
@@ -2193,7 +2271,7 @@ int main(int argc, char **argv)
DLOG_ERR("Invalid port filter : %s\n", optarg);
exit_clean(1);
}
// deny tcp if not set
// deny udp if not set
if (!port_filters_deny_if_empty(&dp->pf_udp))
exit_clean(1);
break;
@@ -2403,6 +2481,9 @@ int main(int argc, char **argv)
case IDX_WF_FILTER_LAN:
wf_filter_lan = !!atoi(optarg);
break;
case IDX_WF_FILTER_LOOPBACK:
wf_filter_loopback = !!atoi(optarg);
break;
case IDX_WF_SAVE:
strncpy(wf_save_file, optarg, sizeof(wf_save_file));
wf_save_file[sizeof(wf_save_file) - 1] = '\0';
@@ -2442,7 +2523,6 @@ int main(int argc, char **argv)
}
else
{
check_dp(dp);
if (bTemplate)
{
if (dp->name && dp_list_search_name(&params.desync_templates, dp->name))
@@ -2572,13 +2652,13 @@ int main(int argc, char **argv)
params.wf_pf_tcp_dst_out, params.wf_pf_tcp_src_out,
params.wf_pf_tcp_dst_in, params.wf_pf_tcp_src_in,
params.wf_pf_udp_dst_in, params.wf_pf_udp_src_out,
&params.wf_raw_part, wf_filter_lan) :
&params.wf_raw_part, wf_filter_lan, wf_filter_loopback) :
wf_make_filter(params.windivert_filter, WINDIVERT_MAX, IfIdx, SubIfIdx, wf_ipv4, wf_ipv6,
wf_tcp_empty,
params.wf_pf_tcp_src_out, params.wf_pf_tcp_dst_out,
params.wf_pf_tcp_src_in, params.wf_pf_tcp_dst_in,
params.wf_pf_udp_src_in, params.wf_pf_udp_dst_out,
&params.wf_raw_part, wf_filter_lan);
&params.wf_raw_part, wf_filter_lan, wf_filter_loopback);
cleanup_windivert_portfilters(&params);
if (!b)
{
@@ -2606,7 +2686,8 @@ int main(int argc, char **argv)
HANDLE hMutexArg;
{
char mutex_name[128];
snprintf(mutex_name, sizeof(mutex_name), "Global\\winws2_arg_%u_%u_%u_%u_%u_%u_%u_%u_%u_%u", hash_wf_tcp_in, hash_wf_udp_in, hash_wf_tcp_out, hash_wf_udp_out, hash_wf_raw, hash_wf_raw_part, hash_ssid_filter, hash_nlm_filter, IfIdx, SubIfIdx, wf_ipv4, wf_ipv6);
snprintf(mutex_name, sizeof(mutex_name), "Global\\winws2_arg_%u_%u_%u_%u_%u_%u_%u_%u_%u_%u_%u_%u",
hash_wf_tcp_in, hash_wf_udp_in, hash_wf_tcp_out, hash_wf_udp_out, hash_wf_raw, hash_wf_raw_part, hash_ssid_filter, hash_nlm_filter, IfIdx, SubIfIdx, wf_ipv4, wf_ipv6);
hMutexArg = CreateMutexA(NULL, TRUE, mutex_name);
if (hMutexArg && GetLastError() == ERROR_ALREADY_EXISTS)
@@ -2657,7 +2738,6 @@ int main(int argc, char **argv)
#error unsupported OS
#endif
ex:
rawsend_cleanup();
cleanup_params(&params);
#ifdef __CYGWIN__
if (hMutexArg)

View File

@@ -12,4 +12,4 @@ extern bool bQuit;
int main(int argc, char *argv[]);
// when something changes that can break LUA compatibility this version should be increased
#define LUA_COMPAT_VER 2
#define LUA_COMPAT_VER 4

View File

@@ -26,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_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_position *pos)
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_positions *tpos)
{
struct rawpacket *rp = malloc(sizeof(struct rawpacket));
if (!rp) return NULL;
@@ -54,13 +54,13 @@ struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sock
rp->len_payload=len_payload;
// make a copy for replay
if (pos)
if (tpos)
{
rp->pos = *pos;
rp->pos_present = true;
rp->tpos = *tpos;
rp->tpos_present = true;
}
else
rp->pos_present = false;
rp->tpos_present = false;
TAILQ_INSERT_TAIL(q, rp, next);

View File

@@ -16,8 +16,8 @@ struct rawpacket
uint32_t fwmark;
size_t len, len_payload;
uint8_t *packet;
t_ctrack_position pos;
bool pos_present;
t_ctrack_positions tpos;
bool tpos_present;
TAILQ_ENTRY(rawpacket) next;
};
TAILQ_HEAD(rawpacket_tailhead, rawpacket);
@@ -26,6 +26,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_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_position *pos);
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_positions *tpos);
struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q);
void rawpacket_free(struct rawpacket *rp);

View File

@@ -112,7 +112,7 @@ int DLOG_FILENAME_VA(const char *filename, const char *format, va_list args)
typedef void (*f_log_function)(int priority, const char *line);
static char log_buf[1024];
static char log_buf[4096];
static size_t log_buf_sz=0;
static void syslog_log_function(int priority, const char *line)
{
@@ -158,11 +158,18 @@ static void android_log_function(int priority, const char *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)
if (vsnprintf(log_buf+log_buf_sz,sizeof(log_buf)-log_buf_sz-1,format,args)>0)
{
log_buf_sz=strlen(log_buf);
// log when buffer is full or buffer ends with \n
if (log_buf_sz>=(sizeof(log_buf)-1) || (log_buf_sz && log_buf[log_buf_sz-1]=='\n'))
if (log_buf_sz==(sizeof(log_buf)-2))
{
log_buf[log_buf_sz++] = '\n';
log_buf[log_buf_sz] = 0;
log_function(syslog_priority,log_buf);
log_buf_sz = 0;
}
else if (log_buf_sz && log_buf[log_buf_sz-1]=='\n')
{
log_function(syslog_priority,log_buf);
log_buf_sz = 0;
@@ -342,6 +349,11 @@ void dp_init(struct desync_profile *dp)
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->hostlist_auto_retrans_maxseq = HOSTLIST_AUTO_RETRANS_MAXSEQ;
dp->hostlist_auto_retrans_reset = true;
dp->hostlist_auto_incoming_maxseq = HOSTLIST_AUTO_INCOMING_MAXSEQ;
dp->hostlist_auto_udp_out = HOSTLIST_AUTO_UDP_OUT;
dp->hostlist_auto_udp_in = HOSTLIST_AUTO_UDP_IN;
dp->filter_ipv4 = dp->filter_ipv6 = true;
}
static void dp_clear_dynamic(struct desync_profile *dp)
@@ -484,6 +496,9 @@ void cleanup_params(struct params_s *params)
hostlist_files_destroy(&params->hostlists);
ipset_files_destroy(&params->ipsets);
ipcacheDestroy(&params->ipcache);
blob_collection_destroy(&params->blobs);
strlist_destroy(&params->lua_init_scripts);
#ifdef __CYGWIN__
strlist_destroy(&params->ssid_filter);
strlist_destroy(&params->nlm_filter);
@@ -517,6 +532,8 @@ void init_params(struct params_s *params)
LIST_INIT(&params->blobs);
LIST_INIT(&params->lua_init_scripts);
params->reasm_payload_disable = params->payload_disable = 1<<L7P_NONE;
#ifdef __CYGWIN__
LIST_INIT(&params->ssid_filter);
LIST_INIT(&params->nlm_filter);

View File

@@ -21,8 +21,6 @@
#include <wordexp.h>
#endif
#define TLS_PARTIALS_ENABLE true
#define RAW_SNDBUF (64*1024) // in bytes
#define Q_MAXLEN 1024 // in packets
@@ -30,6 +28,10 @@
#define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3
#define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60
#define HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT 3
#define HOSTLIST_AUTO_RETRANS_MAXSEQ 32768
#define HOSTLIST_AUTO_INCOMING_MAXSEQ 4096
#define HOSTLIST_AUTO_UDP_OUT 4
#define HOSTLIST_AUTO_UDP_IN 1
#define IPCACHE_LIFETIME 7200
@@ -39,9 +41,9 @@
#define BLOB_EXTRA_BYTES 128
// this MSS is used for ipv6 in windows and linux
#define DEFAULT_MSS 1360
#define DEFAULT_MSS 1220
#define RECONSTRUCT_MAX_SIZE 16384
#define RECONSTRUCT_MAX_SIZE 65536
#define LUA_GC_INTERVAL 60
@@ -78,6 +80,9 @@ struct desync_profile
// pointer to autohostlist. NULL if no autohostlist for the profile.
struct hostlist_file *hostlist_auto;
int hostlist_auto_fail_threshold, hostlist_auto_fail_time, hostlist_auto_retrans_threshold;
int hostlist_auto_udp_in, hostlist_auto_udp_out;
uint32_t hostlist_auto_retrans_maxseq, hostlist_auto_incoming_maxseq;
bool hostlist_auto_retrans_reset;
hostfail_pool *hostlist_auto_fail_counters;
@@ -169,12 +174,14 @@ struct params_s
unsigned int ipcache_lifetime;
ip_cache ipcache;
uint64_t reasm_payload_disable;
uint64_t payload_disable;
struct str_list_head lua_init_scripts;
bool writeable_dir_enable;
char writeable_dir[PATH_MAX];
int lua_gc;
int ref_desync_ctx; // desync ctx userdata registry ref
lua_State *L;
};

View File

@@ -98,6 +98,7 @@ hostfail_pool *HostFailPoolFind(hostfail_pool *p,const char *s)
}
void HostFailPoolDel(hostfail_pool **p, hostfail_pool *elem)
{
free(elem->str);
HASH_DEL(*p, elem);
free(elem);
}
@@ -108,11 +109,7 @@ void HostFailPoolPurge(hostfail_pool **pp)
HASH_ITER(hh, *pp, elem, tmp)
{
if (now >= elem->expire)
{
free(elem->str);
HASH_DEL(*pp, elem);
free(elem);
}
HostFailPoolDel(pp, elem);
}
}
static time_t host_fail_purge_prev=0;
@@ -138,13 +135,17 @@ void HostFailPoolDump(hostfail_pool *p)
static struct str_list *strlist_entry_alloc(const char *str)
{
struct str_list *entry = malloc(sizeof(struct str_list));
if (!entry) return false;
entry->str = strdup(str);
if (!entry->str)
if (!entry) return NULL;
if (str)
{
free(entry);
return NULL;
if (!(entry->str = strdup(str)))
{
free(entry);
return NULL;
}
}
else
entry->str = NULL;
return entry;
}
@@ -244,14 +245,13 @@ static struct str2_list *str2list_entry_copy(const struct str2_list *entry)
{
struct str2_list *e2 = str2list_entry_alloc();
if (!e2) return NULL;
e2->str1 = strdup(entry->str1);
e2->str2 = strdup(entry->str2);
if (!e2->str1 || !e2->str2)
{
str2list_entry_destroy(e2);
return false;
}
if (entry->str1) if (!(e2->str1 = strdup(entry->str1))) goto err;
if (entry->str2) if (!(e2->str2 = strdup(entry->str2))) goto err;
return e2;
err:
str2list_entry_destroy(e2);
return NULL;
}
bool str2list_copy(struct str2_list_head *to, const struct str2_list_head *from)
{
@@ -287,7 +287,7 @@ void funclist_destroy(struct func_list_head *head)
static struct func_list *funclist_entry_alloc(const char *func)
{
struct func_list *entry = malloc(sizeof(struct func_list));
if (!entry) return false;
if (!entry) return NULL;
entry->func = strdup(func);
if (!entry->func)
{
@@ -321,7 +321,7 @@ static struct func_list *funclist_entry_copy(const struct func_list *entry)
if (!str2list_copy(&e2->args, &entry->args))
{
funclist_entry_destroy(e2);
return false;
return NULL;
}
return e2;
}
@@ -350,7 +350,7 @@ struct hostlist_file *hostlist_files_add(struct hostlist_files_head *head, const
if (!(entry->filename = strdup(filename)))
{
free(entry);
return false;
return NULL;
}
}
else
@@ -616,7 +616,7 @@ struct ipset_file *ipset_files_add(struct ipset_files_head *head, const char *fi
if (!(entry->filename = strdup(filename)))
{
free(entry);
return false;
return NULL;
}
}
else

View File

@@ -29,7 +29,9 @@ static bool FindNLD(const uint8_t *dom, size_t dlen, int level, const uint8_t **
return true;
}
static const char *l7proto_name[] = {"all","unknown","known","http","tls","quic","wireguard","dht","discord","stun","xmpp","dns","mtproto"};
static const char *l7proto_name[] = {
"all","unknown","known","http","tls","dtls","quic","wireguard","dht","discord","stun","xmpp","dns","mtproto"
};
const char *l7proto_str(t_l7proto l7)
{
if (l7>=L7_LAST) return NULL;
@@ -46,7 +48,11 @@ bool l7_proto_match(t_l7proto l7proto, uint64_t filter_l7)
}
static const char *l7payload_name[] = {
"all","unknown","empty","known","http_req","http_reply","tls_client_hello","tls_server_hello","quic_initial",
"all","unknown","empty","known",
"http_req","http_reply",
"tls_client_hello","tls_server_hello",
"dtls_client_hello","dtls_server_hello",
"quic_initial",
"wireguard_initiation","wireguard_response","wireguard_cookie","wireguard_keepalive","wireguard_data",
"dht","discord_ip_discovery","stun",
"xmpp_stream", "xmpp_starttls", "xmpp_proceed", "xmpp_features",
@@ -368,8 +374,10 @@ bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *
// extract 2nd level domains
const char *dhost, *drhost;
if (!FindNLD((uint8_t*)host,strlen(host),2,(const uint8_t**)&dhost,NULL) || !FindNLD((uint8_t*)redirect_host,strlen(redirect_host),2,(const uint8_t**)&drhost,NULL))
if (!FindNLD((uint8_t*)redirect_host,strlen(redirect_host),2,(const uint8_t**)&drhost,NULL))
return false;
if (!FindNLD((uint8_t*)host,strlen(host),2,(const uint8_t**)&dhost,NULL))
return true; // no SLD redirects to SLD
// compare 2nd level domains
return strcasecmp(dhost, drhost)!=0;
@@ -456,9 +464,10 @@ bool IsTLSRecordFull(const uint8_t *data, size_t len)
}
bool IsTLSHandshakeHello(const uint8_t *data, size_t len, uint8_t type, bool bPartialIsOK)
{
// return len >= 1 && (type && data[0]==type || !type && (data[0]==0x01 || data[0]==0x02)) && (bPartialIsOK || IsTLSHandshakeFull(data,len));
return len >= 1 && (type && data[0]==type || !type && (data[0]==0x01 || data[0]==0x02)) && (bPartialIsOK || IsTLSHandshakeFull(data,len));
return len >= 6 &&
(type && data[0]==type || !type && (data[0]==0x01 || data[0]==0x02)) &&
data[4]==0x03 && data[5] <= 0x03 &&
(bPartialIsOK || IsTLSHandshakeFull(data,len));
}
bool IsTLSHandshakeClientHello(const uint8_t *data, size_t len, bool bPartialIsOK)
{
@@ -666,7 +675,7 @@ ssize_t TLSPos(t_marker posmarker, int16_t pos, const uint8_t *data, size_t sz)
case PM_HOST_MIDSLD:
case PM_HOST_ENDSLD:
case PM_SNI_EXT:
if (TLSFindExt(data,sz,0,&ext,&elen,TLS_PARTIALS_ENABLE))
if (TLSFindExt(data,sz,0,&ext,&elen,true))
{
if (posmarker==PM_SNI_EXT)
{
@@ -848,7 +857,7 @@ bool TLSMod(const struct fake_tls_mod *tls_mod, const uint8_t *payload, size_t p
{
if (tls_mod->mod & FAKE_TLS_MOD_DUP_SID)
{
if (IsTLSClientHello(payload, payload_len, false))
if (IsTLSClientHelloPartial(payload, payload_len))
{
if (payload_len < 44)
{
@@ -980,24 +989,18 @@ bool IsQUICCryptoHello(const uint8_t *data, size_t len, size_t *hello_offset, si
uint8_t QUICDraftVersion(uint32_t version)
{
/* IETF Draft versions */
if ((version >> 8) == 0xff0000) {
if ((version >> 8) == 0xff0000)
return (uint8_t)version;
}
/* Facebook mvfst, based on draft -22. */
if (version == 0xfaceb001) {
if (version == 0xfaceb001)
return 22;
}
/* Facebook mvfst, based on draft -27. */
if (version == 0xfaceb002 || version == 0xfaceb00e) {
if (version == 0xfaceb002 || version == 0xfaceb00e)
return 27;
}
/* GQUIC Q050, T050 and T051: they are not really based on any drafts,
* but we must return a sensible value */
if (version == 0x51303530 ||
version == 0x54303530 ||
version == 0x54303531) {
if (version == 0x51303530 || version == 0x54303530 || version == 0x54303531)
return 27;
}
/* https://tools.ietf.org/html/draft-ietf-quic-transport-32#section-15
"Versions that follow the pattern 0x?a?a?a?a are reserved for use in
forcing version negotiation to be exercised"
@@ -1005,19 +1008,17 @@ uint8_t QUICDraftVersion(uint32_t version)
used to select a proper salt (which depends on the version itself), but
we don't have a real version here! Let's hope that we need to handle
only latest drafts... */
if ((version & 0x0F0F0F0F) == 0x0a0a0a0a) {
if ((version & 0x0F0F0F0F) == 0x0a0a0a0a)
return 29;
}
/* QUIC (final?) constants for v1 are defined in draft-33, but draft-34 is the
final draft version */
if (version == 0x00000001) {
if (version == 0x00000001)
return 34;
}
/* QUIC Version 2 */
/* TODO: for the time being use 100 as a number for V2 and let see how v2 drafts evolve */
if (version == 0x709A50C4) {
if ((version == 0x709A50C4) || (version == 0x6b3343cf))
return 100;
}
return 0;
}
@@ -1027,7 +1028,7 @@ static bool is_quic_draft_max(uint32_t draft_version, uint8_t max_version)
}
static bool is_quic_v2(uint32_t version)
{
return version == 0x6b3343cf;
return (version == 0x709A50C4) || (version == 0x6b3343cf);
}
static bool quic_hkdf_expand_label(const uint8_t *secret, uint8_t secret_len, const char *label, uint8_t *out, size_t out_len)
@@ -1308,9 +1309,9 @@ bool QUICDefragCrypto(const uint8_t *clean,size_t clean_len, uint8_t *defrag,siz
bool IsQUICInitial(const uint8_t *data, size_t len)
{
// too small packets are not likely to be initials with client hello
// too small packets are not likely to be initials
// long header, fixed bit
if (len < 256 || (data[0] & 0xC0)!=0xC0) return false;
if (len < 128 || (data[0] & 0xF0)!=0xC0) return false;
uint32_t ver = QUICExtractVersion(data,len);
if (QUICDraftVersion(ver) < 11) return false;
@@ -1321,8 +1322,8 @@ bool IsQUICInitial(const uint8_t *data, size_t len)
uint64_t offset=5, sz;
// DCID. must be present
if (!data[offset] || data[offset] > QUIC_MAX_CID_LENGTH) return false;
// DCID
if (data[offset] > QUIC_MAX_CID_LENGTH) return false;
offset += 1 + data[offset];
// SCID
@@ -1340,8 +1341,7 @@ bool IsQUICInitial(const uint8_t *data, size_t len)
offset += sz;
if (offset > len) return false;
// client hello cannot be too small. likely ACK
return sz>=96;
return true;
}
@@ -1378,28 +1378,32 @@ bool IsDNSResponse(const uint8_t *data, size_t len)
}
bool IsWireguardHandshakeInitiation(const uint8_t *data, size_t len)
{
return len==148 && data[0]==1;
return len==148 && pntoh32(data)==0x01000000;
}
bool IsWireguardHandshakeResponse(const uint8_t *data, size_t len)
{
return len==92 && data[0]==2;
return len==92 && pntoh32(data)==0x02000000;
}
bool IsWireguardHandshakeCookie(const uint8_t *data, size_t len)
{
return len==64 && data[0]==3;
return len==64 && pntoh32(data)==0x03000000;
}
bool IsWireguardData(const uint8_t *data, size_t len)
{
// 16 bytes wg header + min 20 bytes for ipv4 encrypted header + 16 byte auth tag
return len>=52 && data[0]==4;
return len>=52 && pntoh32(data)==0x04000000;
}
bool IsWireguardKeepalive(const uint8_t *data, size_t len)
{
return len==32 && data[0]==4;
return len==32 && pntoh32(data)==0x04000000;
}
bool IsDht(const uint8_t *data, size_t len)
{
return len>=7 && data[0]=='d' && (data[1]=='1' || data[1]=='2') && data[2]==':' && data[len-1]=='e';
return len>=5 && data[0]=='d' && data[2]==':' && data[len-1]=='e' &&
(data[1]=='1' && data[3]=='a' && data[4]=='d' ||
data[1]=='1' && data[3]=='r' && data[4]=='d' ||
data[1]=='2' && data[3]=='i' && data[4]=='p' ||
data[1]=='1' && data[3]=='e' && data[4]=='l');
}
bool IsDiscordIpDiscoveryRequest(const uint8_t *data, size_t len)
{
@@ -1443,3 +1447,22 @@ bool IsMTProto(const uint8_t *data, size_t len)
}
return false;
}
bool IsDTLS(const uint8_t *data, size_t len)
{
return ((len > 13) &&
(data[0]>=0x14 && data[0]<=0x17) && /* Handshake, change-cipher-spec, Application-Data, Alert */
((data[1] == 0xfe && data[2] == 0xff) || /* Versions */
(data[1] == 0xfe && data[2] == 0xfd) ||
(data[1] == 0xfe && data[2] == 0xfc) ||
(data[1] == 0x01 && data[2] == 0x00)) &&
(pntoh16(data+11)+13)<=len);
}
bool IsDTLSClientHello(const uint8_t *data, size_t len)
{
return IsDTLS(data,len) && data[0]==0x16 && data[13]==1;
}
bool IsDTLSServerHello(const uint8_t *data, size_t len)
{
return IsDTLS(data,len) && data[0]==0x16 && data[13]==2;
}

View File

@@ -11,6 +11,7 @@ typedef enum {
L7_KNOWN,
L7_HTTP,
L7_TLS,
L7_DTLS,
L7_QUIC,
L7_WIREGUARD,
L7_DHT,
@@ -19,7 +20,7 @@ typedef enum {
L7_XMPP,
L7_DNS,
L7_MTPROTO,
L7_LAST, L7_INVALID=L7_LAST
L7_LAST, L7_INVALID=L7_LAST, L7_NONE=L7_LAST
} t_l7proto;
const char *l7proto_str(t_l7proto l7);
t_l7proto l7proto_from_name(const char *name);
@@ -34,6 +35,8 @@ typedef enum {
L7P_HTTP_REPLY,
L7P_TLS_CLIENT_HELLO,
L7P_TLS_SERVER_HELLO,
L7P_DTLS_CLIENT_HELLO,
L7P_DTLS_SERVER_HELLO,
L7P_QUIC_INITIAL,
L7P_WIREGUARD_INITIATION,
L7P_WIREGUARD_RESPONSE,
@@ -50,7 +53,7 @@ typedef enum {
L7P_DNS_QUERY,
L7P_DNS_RESPONSE,
L7P_MTPROTO_INITIAL,
L7P_LAST, L7P_INVALID=L7P_LAST
L7P_LAST, L7P_INVALID=L7P_LAST, L7P_NONE=L7P_LAST
} t_l7payload;
t_l7payload l7payload_from_name(const char *name);
const char *l7payload_str(t_l7payload l7);
@@ -127,7 +130,7 @@ bool TLSHelloExtractHostFromHandshake(const uint8_t *data, size_t len, char *hos
struct fake_tls_mod
{
char sni[128];
char sni[256];
uint32_t mod;
};
#define FAKE_TLS_MOD_RND 0x01
@@ -155,6 +158,10 @@ bool IsDht(const uint8_t *data, size_t len);
bool IsDiscordIpDiscoveryRequest(const uint8_t *data, size_t len);
bool IsStunMessage(const uint8_t *data, size_t len);
bool IsMTProto(const uint8_t *data, size_t len);
bool IsDTLS(const uint8_t *data, size_t len);
bool IsDTLSClientHello(const uint8_t *data, size_t len);
bool IsDTLSServerHello(const uint8_t *data, size_t len);
#define QUIC_MAX_CID_LENGTH 20
typedef struct quic_cid {