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

310 Commits
v0.7.1 ... v0.8

Author SHA1 Message Date
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
70 changed files with 6893 additions and 1076 deletions

View File

@@ -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
gzip lua/*.lua
)
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }}

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
@@ -38,7 +38,7 @@ 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 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

@@ -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
}
@@ -60,8 +60,8 @@ pktws_seqovl_tests_tls()
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

@@ -7,7 +7,7 @@ pktws_check_http()
local PAYLOAD="--payload http_req" split
for split in '' multisplit multidisorder; do
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
@@ -21,7 +21,7 @@ pktws_check_https_tls()
local PAYLOAD="--payload tls_client_hello" ok=0 pre="$3" split
for split in '' multisplit multidisorder; do
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

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

@@ -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,7 +7,7 @@ pktws_check_http3()
[ "$NOTEST_QUIC" = 1 ] && { echo "SKIPPED"; return; }
local repeats fake pos
local repeats fake pos fool
local PAYLOAD="--payload quic_initial"
if [ -n "$FAKE_QUIC" ]; then
@@ -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"
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

@@ -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}

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()
{

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 parm9 parm10 parmNA
local v parm parm1 parm2 parm3 parm4 parm5 parm6 parm7 parm8 parm9 parm10 param11 param12 param13 parmNA
eval v="\$$1"
if contains "$v" "$HOSTLIST_MARKER" || contains "$v" "$HOSTLIST_NOAUTO_MARKER"; then
[ "$MODE_FILTER" = hostlist -o "$MODE_FILTER" = autohostlist ] &&
@@ -40,14 +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="${AUTOHOSTLIST_RETRANS_MAXSEQ:+--hostlist-auto-retrans-maxseq=$AUTOHOSTLIST_RETRANS_MAXSEQ}"
parm9="${AUTOHOSTLIST_INCOMING_MAXSEQ:+--hostlist-auto-incoming-maxseq=$AUTOHOSTLIST_INCOMING_MAXSEQ}"
parm10="${AUTOHOSTLIST_UDP_IN:+--hostlist-auto-udp-in=$AUTOHOSTLIST_UDP_IN}"
parm11="${AUTOHOSTLIST_UDP_OUT:+--hostlist-auto-udp-out=$AUTOHOSTLIST_UDP_OUT}"
parm12="--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}${parm8:+ $parm8}${parm9:+ $parm9}${parm10:+ $parm10}${parm11:+ $parm11}"
parmNA="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm10:+ $parm12}"
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

@@ -30,6 +30,7 @@ IP2NET_OPT6="--prefix-length=56-64 --v6-threshold=5"
# 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
@@ -97,11 +98,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

@@ -93,9 +93,54 @@ v0.7
v0.7.1
* init.d: fix non-working incoming redirect
* 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

File diff suppressed because it is too large Load Diff

View File

@@ -8,6 +8,20 @@ VPN. Может использоваться для частичной проз
традиционные Linux-системы, FreeBSD, OpenBSD, Windows. В некоторых случаях возможна самостоятельная прикрутка
решения к различным прошивкам.
[Полный мануал](manual.md)
## Поддержать разработчика
Если вы считаете проект полезным и желаете поддержать разработку, направляйте ваши пожертвования на следующие адреса криптокошельков :
USDT `0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E` (предпочительно сеть ERC-20)
BTC `bc1qhqew3mrvp47uk2vevt5sctp7p2x9m7m5kkchve`
ETH `0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E`
## Чем это отличается от zapret1
zapret2 является дальнейшим развитием проекта zapret.
@@ -22,12 +36,12 @@ zapret2 является дальнейшим развитием проекта
или хотя бы область , в которой их можно искать, плюс владеющий базовыми навыками программирования.
*nfqws2* оставляет в себе практически тот же функционал - распознавание протоколов, реассемблинг, дешифровка, управление профилями, хостлисты, ipset-ы, базовая фильтрация.
Но он полностью лишается возможностей самостоятельно воздействовать на трафик. Часть "дурения" переносится в скриптовой язык программирования LUA.
Но он полностью лишается возможностей самостоятельно воздействовать на трафик. Часть "дурения" переносится в скриптовой язык программирования Lua.
LUA код получает от C кода структурированное представление приходящих пакетов в виде дерева (диссекты), подобного тем, что вы видите в wireshark.
Lua код получает от C кода структурированное представление приходящих пакетов в виде дерева (диссекты), подобного тем, что вы видите в wireshark.
Туда же приходят результаты сборки или дешифровки частей некоторых протоколов (tls, quic).
С код предоставляет функции-хелперы, позволяющие отсылать пакеты, работать с двоичными данными, разбирать TLS, искать маркер-позции и т.д.
Имеется библиотека хелперов, написанных на LUA, а так же готовая библиотека программ атаки на DPI (стратегий), реализующая функции *nfqws1* в расширенном варианте
Имеется библиотека хелперов, написанных на Lua, а так же готовая библиотека программ атаки на DPI (стратегий), реализующая функции *nfqws1* в расширенном варианте
и с большей гибкостью.
Вы всегда сможете взять и дописать что-то свое. В этом и есть смысл, чтобы борьбой с DPI смог заняться любой, кто разбирается в пакетах.
@@ -38,8 +52,8 @@ zapret2 - инструмент для таких энтузиастов. Но э
## С чего начать
Хотелось бы избежать "талмуда" на главной странице. Поэтому начнем со способа запуска *nfqws2* и описания способов портирования стратегий *nfqws1* - как в *nfqws2* сделать то же самое, что можно было в *nfqws1*.
Когда вы поймете как это работает, вы можете посмотреть LUA код, находящийся "под капотом". Разобрать как он работает, попробовать написать что-то свое.
Хотелось бы избежать [талмуда](manual.md) на главной странице. Поэтому начнем со способа запуска *nfqws2* и описания способов портирования стратегий *nfqws1* - как в *nfqws2* сделать то же самое, что можно было в *nfqws1*.
Когда вы поймете как это работает, вы можете посмотреть Lua код, находящийся "под капотом". Разобрать как он работает, попробовать написать что-то свое.
"талмуд" обязательно будет, как он есть у любых более-менее сложных проектов. Он нужен как справочник.
### Механика обработки трафика
@@ -88,11 +102,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]`. В примере реализована стратегия
```
@@ -108,7 +122,7 @@ nfqws --qnum 200 --debug \
Тип пейлоада - тип данных, содержащихся в пакете или группе пакетов. Например, протокол соединения может быть tls, а пейлоады - tls_client_hello, tls_server_hello, unknown.
Другое важное отличие - отсутствие жестко определенных фаз десинхронизации. То, что вы раньше писали как `fake,multisplit` реализуется двумя
последовательно вызываемыми LUA функциями. Их может быть столько, сколько нужно, учитывая логику прохождения пакетов и операций с ними, и у каждой могут быть свои параметры.
последовательно вызываемыми Lua функциями. Их может быть столько, сколько нужно, учитывая логику прохождения пакетов и операций с ними, и у каждой могут быть свои параметры.
Может даже несколько раз вызываться одна и так же функция с разными параметрами. Так, например, можно послать несколько фейков, причем с разными фулингами.
Конкретный вызов `--lua-desync` функции называется инстансом. Инстанс - это связка имени функции, номера вызова внутри профиля и номера самого профиля.
Это похоже на одну программу, которую можно запустить много раз с разными параметрами.
@@ -116,11 +130,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`
@@ -153,15 +167,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 - означает отправить как есть,
@@ -287,22 +301,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.
```
@@ -348,17 +361,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
```
@@ -370,9 +380,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 паттерна.
@@ -403,4 +413,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,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

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

@@ -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.Payload[0]=0x01 or
udp.PayloadLength=92 and udp.Payload[0]=0x02 or
udp.PayloadLength=64 and udp.Payload[0]=0x03

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

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

@@ -287,6 +287,39 @@ 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("fake: '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.
@@ -340,6 +373,7 @@ end
-- nfqws1 : "--dpi-desync=fake"
-- standard args : direction, payload, fooling, ip_id, rawsend, reconstruct, ipfrag
-- arg : blob=<blob> - fake payload
-- 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)
@@ -349,6 +383,10 @@ 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_shim(desync, fake_payload, desync.arg.tls_mod, desync.reasm_data)
@@ -368,6 +406,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 +414,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 +435,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 +465,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 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 +528,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 +542,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 +567,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 +628,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 +636,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
@@ -601,6 +745,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 seqovl pattern
-- 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 +753,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 +764,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 +788,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 +849,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 +857,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 +868,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 +897,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 +961,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 +971,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 +988,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 +1051,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 +1059,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,20 +1,48 @@
-- 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 detectors test potential block conditions for orchestrators
-- 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
-- arg: key - a string - table name inside autostate table. to allow multiple orchestrator instances to use single host storage
function automate_host_record(desync)
local hostkey, askey
if desync.arg.reqhost then
hostkey = desync.track and desync.track.hostname
else
hostkey = 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
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
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
@@ -28,6 +56,7 @@ function automate_host_record(desync)
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 = {}
@@ -65,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
@@ -78,6 +114,19 @@ 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:
@@ -85,46 +134,48 @@ end
-- incoming http redirection
-- outgoing retransmissions
-- udp too much out with too few in
-- arg: seq=<rseq> - tcp: if packet is beyond this relative sequence number treat this connection as successful. default is 64K
-- 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: rst=<rseq> - tcp: maximum relative sequence number to treat incoming RST as DPI reset. default is 1
-- 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, arg)
if crec.nocheck then return false end
local seq_rst = tonumber(arg.rst) or 1
local retrans = tonumber(arg.retrans) or 3
local maxseq = tonumber(arg.seq) or 0x10000
local udp_in = tonumber(arg.udp_in) or 1
local udp_out = tonumber(arg.udp_out) or 4
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 maxseq and seq>maxseq then
DLOG("standard_failure_detector: s"..seq.." is beyond s"..maxseq..". treating connection as successful")
crec.nocheck = true
return false
end
if desync.outgoing then
if #desync.dis.payload>0 and retrans and (crec.retrans or 0)<retrans 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.."/"..retrans)
trigger = crec.retrans>=retrans
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 seq_rst and bitand(desync.dis.tcp.th_flags, TH_RST)~=0 then
trigger = seq<=seq_rst
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"..seq_rst)
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"..seq_rst)
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
@@ -143,13 +194,13 @@ function standard_failure_detector(desync, crec, arg)
end
elseif desync.dis.udp then
if desync.outgoing then
if udp_out then
local udp_in = udp_in or 0
trigger = desync.track.pos.direct.pcounter>=udp_out and desync.track.pos.reverse.pcounter<=udp_in
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
crec.nocheck = true
if b_debug then
DLOG("standard_failure_detector: udp_out "..desync.track.pos.direct.pcounter..">="..udp_out.." udp_in "..desync.track.pos.reverse.pcounter.."<="..udp_in)
DLOG("standard_failure_detector: arg.udp_out "..pos_out..">="..arg.udp_out.." arg.udp_in "..pos_in.."<="..arg.udp_in)
end
end
end
@@ -158,17 +209,102 @@ function standard_failure_detector(desync, crec, arg)
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')
-- works with tcp only
-- 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: 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
-- arg: detector - failure detector function name.
-- 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
-- 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
-- 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)
if not hrec.ctstrategy then
@@ -223,26 +359,11 @@ function circular(ctx, desync)
local verdict = VERDICT_PASS
if hrec.final~=hrec.nstrategy then
local crec = automate_conn_record(desync)
local fails = tonumber(desync.arg.fails) or 3
local maxtime = tonumber(desync.arg.time) or 60
local failure_detector
if desync.arg.detector then
if type(_G[desync.arg.detector])~="function" then
error("circular: invalid failure detector function '"..desync.arg.detector.."'")
end
failure_detector = _G[desync.arg.detector]
else
failure_detector = standard_failure_detector
end
if failure_detector(desync,crec,desync.arg) then
-- failure happened. count failures.
if automate_failure_counter(hrec, crec, fails, maxtime) then
-- counter reaches threshold. 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 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
@@ -271,7 +392,7 @@ 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 : nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-auto.lua --lua-desync=condition:iff=cond_payload_str:pattern=1234 --lua-desync=argdebug:testarg=1 --lua-desync=argdebug:testarg=2:morearg=xyz
-- 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)
@@ -293,7 +414,7 @@ end
-- 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 : nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-auto.lua --lua-desync=condition:iff=cond_random --lua-desync=argdebug:testarg=1 --lua-desync=argdebug:testarg=2:morearg=xyz
-- 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)
@@ -309,7 +430,7 @@ end
-- 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 : nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-auto.lua --in-range=-s1 --lua-desync=circular --lua-desync=stopif:iff=cond_random:strategy=1 --lua-desync=argdebug:strategy=1 --lua-desync=argdebug:strategy=2
-- 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)
@@ -321,3 +442,61 @@ function stopif(ctx, desync)
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

@@ -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,39 +264,44 @@ 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))
test_assert(v2==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)
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))
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,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)
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)
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))
test_assert(v2==v3)
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)
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_ux()
@@ -305,7 +310,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 +321,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

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

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

@@ -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);
}
@@ -127,7 +127,7 @@ static t_conntrack_pool *ConntrackNew(t_conntrack_pool **pp, const t_conn *c)
return ctnew;
}
static void ConntrackApplyPos(const struct tcphdr *tcp, t_ctrack *t, bool bReverse, uint32_t len_payload)
static void ConntrackApplyPos(t_ctrack *t, bool bReverse, const struct dissect *dis)
{
uint8_t scale;
uint16_t mss;
@@ -136,29 +136,35 @@ static void ConntrackApplyPos(const struct tcphdr *tcp, t_ctrack *t, bool bRever
direct = bReverse ? &t->pos.server : &t->pos.client;
reverse = bReverse ? &t->pos.client : &t->pos.server;
scale = tcp_find_scale_factor(tcp);
mss = ntohs(tcp_find_mss(tcp));
if (dis->ip6) direct->ip6flow = ntohl(dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_flow);
direct->seq_last = ntohl(tcp->th_seq);
direct->pos = direct->seq_last + len_payload;
reverse->pos = reverse->seq_last = ntohl(tcp->th_ack);
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 (len_payload)
else if (dis->len_payload)
{
direct->uppos_prev = direct->uppos;
if (!((direct->pos - direct->uppos) & 0x80000000))
direct->uppos = direct->pos;
}
direct->winsize = ntohs(tcp->th_win);
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;
}
// 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 ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct dissect *dis)
{
uint8_t scale;
uint16_t mss;
@@ -166,34 +172,34 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
if (bReverse)
{
t->pos.server.pcounter++;
t->pos.server.pdcounter += !!len_payload;
t->pos.server.pbcounter += len_payload;
t->pos.server.pdcounter += !!dis->len_payload;
t->pos.server.pbcounter += dis->len_payload;
}
else
{
t->pos.client.pcounter++;
t->pos.client.pdcounter += !!len_payload;
t->pos.client.pbcounter += len_payload;
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.client.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;
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.client.seq0) t->pos.client.seq0 = seq0;
t->pos.server.seq0 = ntohl(tcphdr->th_seq);
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;
}
@@ -202,36 +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.server.seq0) t->pos.server.seq0 = ntohl(tcphdr->th_ack) - 1;
if (!bReverse && !t->pos.server.seq0) t->pos.server.seq0 = ntohl(dis->tcp->th_ack) - 1;
}
}
ConntrackApplyPos(tcphdr, t, bReverse, len_payload);
}
else
{
if (bReverse)
{
t->pos.server.seq_last = t->pos.server.pos;
t->pos.server.pos += len_payload;
}
else
{
t->pos.client.seq_last = t->pos.client.pos;
t->pos.client.pos += len_payload;
}
ConntrackApplyPos(t, bReverse, dis);
}
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;
@@ -250,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
@@ -273,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;
}
}
@@ -293,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);
@@ -312,9 +306,9 @@ 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)

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
@@ -100,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
@@ -17,17 +18,19 @@ typedef struct
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
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
// tcp only state, not used in udp
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

View File

@@ -547,6 +547,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)
{
@@ -718,13 +745,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;
@@ -734,8 +784,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;
}
@@ -1253,14 +1304,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;

View File

@@ -162,6 +162,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);

View File

@@ -246,11 +246,13 @@ static bool is_retransmission(const t_ctrack_position *pos)
}
// return true if retrans trigger fires
static bool auto_hostlist_retrans(t_ctrack *ctrack, uint8_t l4proto, int threshold, const char *client_ip_port, t_l7proto l7proto)
static bool auto_hostlist_retrans
(t_ctrack *ctrack, const struct dissect *dis, int threshold, const char *client_ip_port, t_l7proto l7proto,
const struct sockaddr *client, const char *ifclient)
{
if (ctrack && ctrack->dp && ctrack->hostname_ah_check && !ctrack->failure_detect_finalized && ctrack->req_retrans_counter != RETRANS_COUNTER_STOP)
{
if (l4proto == IPPROTO_TCP && ctrack->pos.state!=SYN)
if (dis->proto == IPPROTO_TCP && ctrack->pos.state!=SYN)
{
if (!seq_within(ctrack->pos.client.seq_last, ctrack->pos.client.seq0, ctrack->pos.client.seq0 + ctrack->dp->hostlist_auto_retrans_maxseq))
{
@@ -269,6 +271,46 @@ static bool auto_hostlist_retrans(t_ctrack *ctrack, uint8_t l4proto, int thresho
DLOG("retrans threshold reached : %u/%u\n", ctrack->req_retrans_counter, threshold);
ctrack_stop_retrans_counter(ctrack);
ctrack->failure_detect_finalized = true;
if (dis->tcp && ctrack->dp->hostlist_auto_retrans_reset && (dis->ip || dis->ip6))
{
uint8_t pkt[sizeof(struct ip6_hdr)+sizeof(struct tcphdr)];
struct ip *ip;
struct ip6_hdr *ip6;
struct tcphdr *tcp;
uint16_t pktlen;
if (dis->ip)
{
ip = (struct ip*)pkt; ip6=NULL;
pktlen = sizeof(struct ip) + sizeof(struct tcphdr);
*ip = *dis->ip;
ip->ip_hl = sizeof(struct ip)/4; // remove ip options
ip->ip_len = htons(pktlen);
ip->ip_id=0;
tcp = (struct tcphdr*)(ip+1);
*tcp = *dis->tcp;
}
else if (dis->ip6)
{
ip6 = (struct ip6_hdr*)pkt; ip=NULL;
pktlen = sizeof(struct ip6_hdr) + sizeof(struct tcphdr);
*ip6 = *dis->ip6;
ip6->ip6_plen = htons(sizeof(struct tcphdr));
ip6->ip6_nxt = IPPROTO_TCP;
ip6->ip6_ctlun.ip6_un1.ip6_un1_flow = htonl(ctrack->pos.server.ip6flow ? ctrack->pos.server.ip6flow : 0x60000000);
tcp = (struct tcphdr*)(ip6+1);
*tcp = *dis->tcp;
}
reverse_ip(ip,ip6); // also fixes ip4 checksum
reverse_tcp(tcp);
tcp->th_off = sizeof(struct tcphdr)/4; // remove tcp options
tcp->th_flags = TH_RST;
tcp->th_win = ctrack->pos.server.winsize;
tcp_fix_checksum(tcp, sizeof(struct tcphdr), ip, ip6);
DLOG("sending RST to retransmitter. ifname=%s\n", ifclient ? ifclient : "");
rawsend(client,0,ifclient,pkt,pktlen);
}
return true;
}
DLOG("retrans counter : %u/%u\n", ctrack->req_retrans_counter, threshold);
@@ -330,13 +372,13 @@ static void fill_client_ip_port(const struct sockaddr *client, char *client_ip_p
else
*client_ip_port = 0;
}
static void process_retrans_fail(t_ctrack *ctrack, uint8_t proto, const struct sockaddr *client)
static void process_retrans_fail(t_ctrack *ctrack, const struct dissect *dis, struct sockaddr *client, const char *ifclient)
{
if (params.server) return; // no autohostlists in server mode
char client_ip_port[48];
fill_client_ip_port(client, client_ip_port, sizeof(client_ip_port));
if (ctrack && ctrack->dp && ctrack->hostname && auto_hostlist_retrans(ctrack, proto, ctrack->dp->hostlist_auto_retrans_threshold, client_ip_port, ctrack->l7proto))
if (ctrack && ctrack->dp && ctrack->hostname && auto_hostlist_retrans(ctrack, dis, ctrack->dp->hostlist_auto_retrans_threshold, client_ip_port, ctrack->l7proto, client, ifclient))
{
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : retrans threshold reached", ctrack->hostname, ctrack->dp->n, PROFILE_NAME(ctrack->dp), client_ip_port, l7proto_str(ctrack->l7proto));
auto_hostlist_failed(ctrack->dp, ctrack->hostname, ctrack->hostname_is_ip, client_ip_port, ctrack->l7proto);
@@ -415,7 +457,8 @@ static bool reasm_start(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, ui
static bool reasm_client_start(t_ctrack *ctrack, uint8_t proto, size_t sz, size_t szMax, const uint8_t *data_payload, size_t len_payload)
{
if (!ctrack) return false;
if (proto==IPPROTO_TCP && ctrack->pos.server.winsize_calc < sz)
// if winsize_calc==0 it means we dont know server window size - no incoming packets redirected ?
if (proto==IPPROTO_TCP && ctrack->pos.server.winsize_calc && (ctrack->pos.server.winsize_calc < sz))
{
// this is rare but possible situation
// server gave us too small tcp window
@@ -505,7 +548,10 @@ static uint8_t ct_new_postnat_fix(const t_ctrack *ctrack, const struct dissect *
return VERDICT_DROP;
}
static bool pos_overflow(const t_ctrack_position *pos, char mode)
{
return (mode=='s' || mode=='p') && pos && pos->rseq_over_2G;
}
static uint64_t pos_get(const t_ctrack_position *pos, char mode)
{
if (pos)
@@ -524,7 +570,7 @@ static uint64_t pos_get(const t_ctrack_position *pos, char mode)
static bool check_pos_from(const t_ctrack_position *pos, const struct packet_range *range)
{
uint64_t ps;
if (range->from.mode == 'x') return false;
if ((range->from.mode == 'x') || pos_overflow(pos,range->from.mode)) return false;
if (range->from.mode != 'a')
{
if (pos)
@@ -540,7 +586,7 @@ static bool check_pos_from(const t_ctrack_position *pos, const struct packet_ran
static bool check_pos_to(const t_ctrack_position *pos, const struct packet_range *range)
{
uint64_t ps;
if (range->to.mode == 'x') return false;
if (range->to.mode == 'x' || pos_overflow(pos,range->to.mode)) return false;
if (range->to.mode != 'a')
{
if (pos)
@@ -707,7 +753,7 @@ static uint8_t desync(
struct func_list *func;
int ref_arg = LUA_NOREF, status;
bool b, b_cutoff_all, b_unwanted_payload;
t_lua_desync_context ctx = { .dp = dp, .ctrack = ctrack, .dis = dis, .cancel = false, .incoming = bIncoming };
t_lua_desync_context ctx = { .magic = 0, .dp = dp, .ctrack = ctrack, .dis = dis, .cancel = false, .incoming = bIncoming };
const char *sDirection = bIncoming ? "in" : "out";
struct packet_range *range;
size_t l;
@@ -754,10 +800,12 @@ static uint8_t desync(
DLOG("* lua '%s' : voluntary cutoff\n", instance);
else if (check_pos_cutoff(pos, range))
{
DLOG("* lua '%s' : %s pos %c%llu %c%llu is beyond range %c%u%c%c%u (ctrack %s)\n",
DLOG("* lua '%s' : %s pos %c%llu %c%llu overflow %u %u is beyond range %c%u%c%c%u (ctrack %s)\n",
instance, sDirection,
range->from.mode, pos_get(pos, range->from.mode),
range->to.mode, pos_get(pos, range->to.mode),
pos_overflow(pos, range->from.mode),
pos_overflow(pos, range->to.mode),
range->from.mode, range->from.pos,
range->upper_cutoff ? '<' : '-',
range->to.mode, range->to.pos,
@@ -855,8 +903,14 @@ static uint8_t desync(
lua_pushf_str("func", func->func);
lua_pushf_int("func_n", ctx.func_n);
lua_pushf_str("func_instance", instance);
int initial_stack_top = lua_gettop(params.L);
// lua should not store and access ctx outside of this call
// if this happens make our best to prevent access to bad memory
// this is not crash-proof but better than nothing
ctx.magic = MAGIC_CTX; // mark struct as valid
status = lua_pcall(params.L, 2, LUA_MULTRET, 0);
ctx.magic = 0; // mark struct as invalid
if (status)
{
lua_dlog_error();
@@ -975,6 +1029,23 @@ static void setup_direction(
}
}
static void dp_changed(t_ctrack *ctrack)
{
if (ctrack)
{
if (ctrack->b_lua_in_cutoff)
{
DLOG("clearing lua in cutoff because of profile change\n");
ctrack->b_lua_in_cutoff = false;
}
if (ctrack->b_lua_out_cutoff)
{
DLOG("clearing lua out cutoff because of profile change\n");
ctrack->b_lua_out_cutoff = false;
}
}
}
static uint8_t dpi_desync_tcp_packet_play(
unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset,
uint32_t fwmark,
@@ -1007,7 +1078,7 @@ static uint8_t dpi_desync_tcp_packet_play(
// in replay mode conntrack_replay is not NULL and ctrack is NULL
//ConntrackPoolDump(&params.conntrack);
if (!ConntrackPoolDoubleSearch(&params.conntrack, dis->ip, dis->ip6, dis->tcp, NULL, &ctrack_replay, &bReverse) || bReverse)
if (!ConntrackPoolDoubleSearch(&params.conntrack, dis, &ctrack_replay, &bReverse) || bReverse)
return verdict;
bReverseFixed = bReverse ^ params.server;
setup_direction(dis, bReverseFixed, &src, &dst, &sdip4, &sdip6, &sdport);
@@ -1039,7 +1110,7 @@ static uint8_t dpi_desync_tcp_packet_play(
if (!params.ctrack_disable)
{
ConntrackPoolPurge(&params.conntrack);
if (ConntrackPoolFeed(&params.conntrack, dis->ip, dis->ip6, dis->tcp, NULL, dis->len_payload, &ctrack, &bReverse))
if (ConntrackPoolFeed(&params.conntrack, dis, &ctrack, &bReverse))
{
dp = ctrack->dp;
ctrack_replay = ctrack;
@@ -1115,6 +1186,7 @@ static uint8_t dpi_desync_tcp_packet_play(
else
bCheckDone = bCheckResult = bCheckExcluded = false;
bool bHaveHost = false, bHostIsIp = false;
if (bReverse)
{
// protocol detection
@@ -1186,7 +1258,6 @@ static uint8_t dpi_desync_tcp_packet_play(
struct blob_collection_head *fake;
uint8_t *p, *phost = NULL;
int i;
bool bHaveHost = false, bHostIsIp = false;
if (replay_piece_count)
{
@@ -1199,7 +1270,8 @@ static uint8_t dpi_desync_tcp_packet_play(
rlen_payload = ctrack->reasm_client.size_present;
}
process_retrans_fail(ctrack, IPPROTO_TCP, (struct sockaddr*)&src);
process_retrans_fail(ctrack, dis, (struct sockaddr*)&src, ifin);
if (IsHttp(rdata_payload, rlen_payload))
{
DLOG("packet contains HTTP request\n");
@@ -1284,90 +1356,90 @@ static uint8_t dpi_desync_tcp_packet_play(
protocol_probe(testers, sizeof(testers) / sizeof(*testers), dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
}
if (bHaveHost)
{
bHostIsIp = strip_host_to_ip(host);
DLOG("hostname: %s\n", host);
}
}
bool bDiscoveredL7;
if (bHaveHost)
{
bHostIsIp = strip_host_to_ip(host);
DLOG("hostname: %s\n", host);
}
bool bDiscoveredL7;
if (ctrack_replay)
{
if ((bDiscoveredL7 = !ctrack_replay->l7proto_discovered && ctrack_replay->l7proto != L7_UNKNOWN))
ctrack_replay->l7proto_discovered = true;
}
else
bDiscoveredL7 = l7proto != L7_UNKNOWN;
if (bDiscoveredL7) DLOG("discovered l7 protocol\n");
bool bDiscoveredHostname = bHaveHost && !(ctrack_replay && ctrack_replay->hostname_discovered);
if (bDiscoveredHostname)
{
DLOG("discovered hostname\n");
if (ctrack_replay)
{
bDiscoveredL7 = !ctrack_replay->l7proto_discovered && ctrack_replay->l7proto != L7_UNKNOWN;
ctrack_replay->l7proto_discovered = true;
}
else
bDiscoveredL7 = l7proto != L7_UNKNOWN;
if (bDiscoveredL7) DLOG("discovered l7 protocol\n");
bool bDiscoveredHostname = bHaveHost && !(ctrack_replay && ctrack_replay->hostname_discovered);
if (bDiscoveredHostname)
{
DLOG("discovered hostname\n");
if (ctrack_replay)
free(ctrack_replay->hostname);
ctrack_replay->hostname = strdup(host);
ctrack_replay->hostname_is_ip = bHostIsIp;
if (!ctrack_replay->hostname)
{
free(ctrack_replay->hostname);
ctrack_replay->hostname = strdup(host);
ctrack_replay->hostname_is_ip = bHostIsIp;
if (!ctrack_replay->hostname)
{
DLOG_ERR("hostname dup : out of memory");
goto pass_reasm_cancel;
}
ctrack_replay->hostname_discovered = true;
if (!ipcache_put_hostname(sdip4, sdip6, host, bHostIsIp))
goto pass_reasm_cancel;
DLOG_ERR("hostname dup : out of memory");
goto pass_reasm_cancel;
}
}
ctrack_replay->hostname_discovered = true;
if (!ipcache_put_hostname(sdip4, sdip6, host, bHostIsIp))
goto pass_reasm_cancel;
}
}
if (bDiscoveredL7 || bDiscoveredHostname)
if (bDiscoveredL7 || bDiscoveredHostname)
{
struct desync_profile *dp_prev = dp;
// search for desync profile again. it may have changed.
dp = dp_find(&params.desync_profiles, IPPROTO_TCP, sdip4, sdip6, sdport,
ctrack_replay ? ctrack_replay->hostname : bHaveHost ? host : NULL,
ctrack_replay ? ctrack_replay->hostname_is_ip : bHostIsIp,
l7proto, ssid,
&bCheckDone, &bCheckResult, &bCheckExcluded);
if (ctrack_replay)
{
struct desync_profile *dp_prev = dp;
// search for desync profile again. it may have changed.
dp = dp_find(&params.desync_profiles, IPPROTO_TCP, sdip4, sdip6, sdport,
ctrack_replay ? ctrack_replay->hostname : bHaveHost ? host : NULL,
ctrack_replay ? ctrack_replay->hostname_is_ip : bHostIsIp,
l7proto, ssid,
&bCheckDone, &bCheckResult, &bCheckExcluded);
ctrack_replay->dp = dp;
ctrack_replay->dp_search_complete = true;
ctrack_replay->bCheckDone = bCheckDone;
ctrack_replay->bCheckResult = bCheckResult;
ctrack_replay->bCheckExcluded = bCheckExcluded;
}
if (!dp) goto pass_reasm_cancel;
if (dp != dp_prev)
{
dp_changed(ctrack_replay);
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
}
}
if (bHaveHost && !PROFILE_HOSTLISTS_EMPTY(dp))
{
if (!bCheckDone)
{
bCheckResult = HostlistCheck(dp, host, bHostIsIp, &bCheckExcluded, false);
bCheckDone = true;
if (ctrack_replay)
{
ctrack_replay->dp = dp;
ctrack_replay->dp_search_complete = true;
ctrack_replay->bCheckDone = bCheckDone;
ctrack_replay->bCheckResult = bCheckResult;
ctrack_replay->bCheckExcluded = bCheckExcluded;
}
if (!dp) goto pass_reasm_cancel;
if (dp != dp_prev)
{
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
}
}
if (bHaveHost && !PROFILE_HOSTLISTS_EMPTY(dp))
if (bCheckResult)
ctrack_stop_retrans_counter(ctrack_replay);
else
{
if (!bCheckDone)
if (ctrack_replay)
{
bCheckResult = HostlistCheck(dp, host, bHostIsIp, &bCheckExcluded, false);
bCheckDone = true;
if (ctrack_replay)
{
ctrack_replay->bCheckDone = bCheckDone;
ctrack_replay->bCheckResult = bCheckResult;
ctrack_replay->bCheckExcluded = bCheckExcluded;
}
}
if (bCheckResult)
ctrack_stop_retrans_counter(ctrack_replay);
else
{
if (ctrack_replay)
{
ctrack_replay->hostname_ah_check = dp->hostlist_auto && !bCheckExcluded;
if (!ctrack_replay->hostname_ah_check)
ctrack_stop_retrans_counter(ctrack_replay);
}
ctrack_replay->hostname_ah_check = dp->hostlist_auto && !bCheckExcluded;
if (!ctrack_replay->hostname_ah_check)
ctrack_stop_retrans_counter(ctrack_replay);
}
}
}
@@ -1400,6 +1472,26 @@ static void quic_reasm_cancel(t_ctrack *ctrack, const char *reason)
DLOG("%s\n", reason);
}
static void udp_standard_protocol_probe(const uint8_t *data_payload, size_t len_payload, t_ctrack *ctrack, t_l7proto *l7proto, t_l7payload *l7payload)
{
t_protocol_probe testers[] = {
{L7P_QUIC_INITIAL,L7_QUIC,IsQUICInitial,false},
{L7P_DISCORD_IP_DISCOVERY,L7_DISCORD,IsDiscordIpDiscoveryRequest,false},
{L7P_STUN,L7_STUN,IsStunMessage,false},
{L7P_DNS_QUERY,L7_DNS,IsDNSQuery,false},
{L7P_DNS_RESPONSE,L7_DNS,IsDNSResponse,false},
{L7P_DHT,L7_DHT,IsDht,false},
{L7P_DTLS_CLIENT_HELLO,L7_DTLS,IsDTLSClientHello,false},
{L7P_DTLS_SERVER_HELLO,L7_DTLS,IsDTLSServerHello,false},
{L7P_WIREGUARD_INITIATION,L7_WIREGUARD,IsWireguardHandshakeInitiation,false},
{L7P_WIREGUARD_RESPONSE,L7_WIREGUARD,IsWireguardHandshakeResponse,false},
{L7P_WIREGUARD_COOKIE,L7_WIREGUARD,IsWireguardHandshakeCookie,false},
{L7P_WIREGUARD_KEEPALIVE,L7_WIREGUARD,IsWireguardKeepalive,false},
{L7P_WIREGUARD_DATA,L7_WIREGUARD,IsWireguardData,true}};
protocol_probe(testers, sizeof(testers) / sizeof(*testers), data_payload, len_payload, ctrack, l7proto, l7payload);
}
static uint8_t dpi_desync_udp_packet_play(
unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset,
@@ -1450,7 +1542,7 @@ static uint8_t dpi_desync_udp_packet_play(
// in replay mode conntrack_replay is not NULL and ctrack is NULL
//ConntrackPoolDump(&params.conntrack);
if (!ConntrackPoolDoubleSearch(&params.conntrack, dis->ip, dis->ip6, NULL, dis->udp, &ctrack_replay, &bReverse) || bReverse)
if (!ConntrackPoolDoubleSearch(&params.conntrack, dis, &ctrack_replay, &bReverse) || bReverse)
return verdict;
bReverseFixed = bReverse ^ params.server;
setup_direction(dis, bReverseFixed, &src, &dst, &sdip4, &sdip6, &sdport);
@@ -1482,7 +1574,7 @@ static uint8_t dpi_desync_udp_packet_play(
if (!params.ctrack_disable)
{
ConntrackPoolPurge(&params.conntrack);
if (ConntrackPoolFeed(&params.conntrack, dis->ip, dis->ip6, NULL, dis->udp, dis->len_payload, &ctrack, &bReverse))
if (ConntrackPoolFeed(&params.conntrack, dis, &ctrack, &bReverse))
{
dp = ctrack->dp;
ctrack_replay = ctrack;
@@ -1559,24 +1651,14 @@ static uint8_t dpi_desync_udp_packet_play(
if (dis->len_payload)
{
bool bHaveHost = false, bHostIsIp = false;
if (bReverse)
{
t_protocol_probe testers[] = {
{L7P_DNS_RESPONSE,L7_DNS,IsDNSResponse,false},
{L7P_DHT,L7_DHT,IsDht,false},
{L7P_STUN,L7_STUN,IsStunMessage,false},
{L7P_WIREGUARD_INITIATION,L7_WIREGUARD,IsWireguardHandshakeInitiation,false},
{L7P_WIREGUARD_RESPONSE,L7_WIREGUARD,IsWireguardHandshakeResponse,false},
{L7P_WIREGUARD_COOKIE,L7_WIREGUARD,IsWireguardHandshakeCookie,false},
{L7P_WIREGUARD_KEEPALIVE,L7_WIREGUARD,IsWireguardKeepalive,false},
{L7P_WIREGUARD_DATA,L7_WIREGUARD,IsWireguardData,true}
};
protocol_probe(testers, sizeof(testers) / sizeof(*testers), dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
udp_standard_protocol_probe(dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
}
else
{
struct blob_collection_head *fake;
bool bHaveHost = false, bHostIsIp = false;
if (IsQUICInitial(dis->data_payload, dis->len_payload))
{
DLOG("packet contains QUIC initial\n");
@@ -1709,114 +1791,97 @@ static uint8_t dpi_desync_udp_packet_play(
}
else // not QUIC initial
{
// received payload without host. it means we are out of the request retransmission phase. stop counter
ctrack_stop_retrans_counter(ctrack);
// not quic initial - stop reasm
reasm_client_cancel(ctrack);
t_protocol_probe testers[] = {
{L7P_DISCORD_IP_DISCOVERY,L7_DISCORD,IsDiscordIpDiscoveryRequest,false},
{L7P_STUN,L7_STUN,IsStunMessage,false},
{L7P_DNS_QUERY,L7_DNS,IsDNSQuery,false},
{L7P_DHT,L7_DHT,IsDht,false},
{L7P_WIREGUARD_INITIATION,L7_WIREGUARD,IsWireguardHandshakeInitiation,false},
{L7P_WIREGUARD_RESPONSE,L7_WIREGUARD,IsWireguardHandshakeResponse,false},
{L7P_WIREGUARD_COOKIE,L7_WIREGUARD,IsWireguardHandshakeCookie,false},
{L7P_WIREGUARD_KEEPALIVE,L7_WIREGUARD,IsWireguardKeepalive,false},
{L7P_WIREGUARD_DATA,L7_WIREGUARD,IsWireguardData,true}
};
protocol_probe(testers, sizeof(testers) / sizeof(*testers), dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
udp_standard_protocol_probe(dis->data_payload, dis->len_payload, ctrack, &l7proto, &l7payload);
}
}
if (bHaveHost)
{
bHostIsIp = strip_host_to_ip(host);
DLOG("hostname: %s\n", host);
}
if (bHaveHost)
{
bHostIsIp = strip_host_to_ip(host);
DLOG("hostname: %s\n", host);
}
bool bDiscoveredL7;
bool bDiscoveredL7;
if (ctrack_replay)
{
if ((bDiscoveredL7 = !ctrack_replay->l7proto_discovered && l7proto != L7_UNKNOWN))
ctrack_replay->l7proto_discovered = true;
}
else
bDiscoveredL7 = l7proto != L7_UNKNOWN;
if (bDiscoveredL7) DLOG("discovered l7 protocol\n");
bool bDiscoveredHostname = bHaveHost && !(ctrack_replay && ctrack_replay->hostname_discovered);
if (bDiscoveredHostname)
{
DLOG("discovered hostname\n");
if (ctrack_replay)
{
bDiscoveredL7 = !ctrack_replay->l7proto_discovered && l7proto != L7_UNKNOWN;
ctrack_replay->l7proto_discovered = true;
}
else
bDiscoveredL7 = l7proto != L7_UNKNOWN;
if (bDiscoveredL7) DLOG("discovered l7 protocol\n");
bool bDiscoveredHostname = bHaveHost && !(ctrack_replay && ctrack_replay->hostname_discovered);
if (bDiscoveredHostname)
{
DLOG("discovered hostname\n");
if (ctrack_replay)
ctrack_replay->hostname_discovered = true;
free(ctrack_replay->hostname);
ctrack_replay->hostname = strdup(host);
ctrack_replay->hostname_is_ip = bHostIsIp;
if (!ctrack_replay->hostname)
{
ctrack_replay->hostname_discovered = true;
free(ctrack_replay->hostname);
ctrack_replay->hostname = strdup(host);
ctrack_replay->hostname_is_ip = bHostIsIp;
if (!ctrack_replay->hostname)
{
DLOG_ERR("hostname dup : out of memory");
goto pass;
}
if (!ipcache_put_hostname(sdip4, sdip6, host, bHostIsIp))
goto pass;
DLOG_ERR("hostname dup : out of memory");
goto pass;
}
if (!ipcache_put_hostname(sdip4, sdip6, host, bHostIsIp))
goto pass;
}
}
if (bDiscoveredL7 || bDiscoveredHostname)
if (bDiscoveredL7 || bDiscoveredHostname)
{
struct desync_profile *dp_prev = dp;
// search for desync profile again. it may have changed.
dp = dp_find(&params.desync_profiles, IPPROTO_UDP, sdip4, sdip6, sdport,
ctrack_replay ? ctrack_replay->hostname : bHaveHost ? host : NULL,
ctrack_replay ? ctrack_replay->hostname_is_ip : bHostIsIp,
l7proto, ssid,
&bCheckDone, &bCheckResult, &bCheckExcluded);
if (ctrack_replay)
{
struct desync_profile *dp_prev = dp;
ctrack_replay->dp = dp;
ctrack_replay->dp_search_complete = true;
ctrack_replay->bCheckDone = bCheckDone;
ctrack_replay->bCheckResult = bCheckResult;
ctrack_replay->bCheckExcluded = bCheckExcluded;
}
if (!dp)
goto pass_reasm_cancel;
if (dp != dp_prev)
{
dp_changed(ctrack_replay);
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
}
}
else if (ctrack_replay)
{
bCheckDone = ctrack_replay->bCheckDone;
bCheckResult = ctrack_replay->bCheckResult;
bCheckExcluded = ctrack_replay->bCheckExcluded;
}
// search for desync profile again. it may have changed.
dp = dp_find(&params.desync_profiles, IPPROTO_UDP, sdip4, sdip6, sdport,
ctrack_replay ? ctrack_replay->hostname : bHaveHost ? host : NULL,
ctrack_replay ? ctrack_replay->hostname_is_ip : bHostIsIp,
l7proto, ssid,
&bCheckDone, &bCheckResult, &bCheckExcluded);
if (bHaveHost && !PROFILE_HOSTLISTS_EMPTY(dp))
{
if (!bCheckDone)
{
bCheckResult = HostlistCheck(dp, host, bHostIsIp, &bCheckExcluded, false);
bCheckDone = true;
if (ctrack_replay)
{
ctrack_replay->dp = dp;
ctrack_replay->dp_search_complete = true;
ctrack_replay->bCheckDone = bCheckDone;
ctrack_replay->bCheckResult = bCheckResult;
ctrack_replay->bCheckExcluded = bCheckExcluded;
}
if (!dp)
goto pass_reasm_cancel;
if (dp != dp_prev)
{
DLOG("desync profile changed by revealed l7 protocol or hostname !\n");
}
}
else if (ctrack_replay)
{
bCheckDone = ctrack_replay->bCheckDone;
bCheckResult = ctrack_replay->bCheckResult;
bCheckExcluded = ctrack_replay->bCheckExcluded;
}
if (bHaveHost && !PROFILE_HOSTLISTS_EMPTY(dp))
{
if (!bCheckDone)
{
bCheckResult = HostlistCheck(dp, host, bHostIsIp, &bCheckExcluded, false);
bCheckDone = true;
if (ctrack_replay)
{
ctrack_replay->bCheckDone = bCheckDone;
ctrack_replay->bCheckResult = bCheckResult;
ctrack_replay->bCheckExcluded = bCheckExcluded;
}
}
if (bCheckResult)
ctrack_stop_retrans_counter(ctrack_replay);
else
{
if (ctrack_replay)
ctrack_replay->hostname_ah_check = dp->hostlist_auto && !bCheckExcluded;
}
}
if (!bCheckResult && ctrack_replay)
ctrack_replay->hostname_ah_check = dp->hostlist_auto && !bCheckExcluded;
}
process_udp_fail(ctrack_replay, tpos, (struct sockaddr*)&src);

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;
@@ -38,7 +38,7 @@ int z_readfile(FILE *F, char **buf, size_t *size)
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 +57,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

@@ -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 swap16(uint16_t u)
{
// __builtin_bswap16 is absent in ancient lexra gcc 4.6
return (u>>8) | ((u&0xFF)<<8);
}
uint32_t swap24(uint32_t u)
{
return (u>>16) & 0xFF | u & 0xFF00 | (u<<16) & 0xFF0000;
}
uint64_t swap48(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)

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 swap16(uint16_t u);
uint32_t swap24(uint32_t u);
uint64_t swap48(uint64_t u);
bool parse_hex_str(const char *s, uint8_t *pbuf, size_t *size);
char hex_digit(uint8_t v);

View File

@@ -61,7 +61,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)
{

View File

@@ -76,7 +76,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)
{

View File

@@ -9,9 +9,11 @@
#elif defined(__CYGWIN__)
#include <processthreadsapi.h>
#endif
#include <errno.h>
#include "lua.h"
#include "params.h"
#include "gzip.h"
#include "helpers.h"
#include "conntrack.h"
#include "crypto/sha.h"
@@ -69,16 +71,16 @@ static int luacall_bitlshift(lua_State *L)
{
lua_check_argc(L,"bitlshift",2);
int64_t v=(int64_t)luaL_checklint(L,1);
if (v>0xFFFFFFFF || v<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
lua_pushlint(L,((uint32_t)v) << luaL_checkinteger(L,2));
if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
lua_pushlint(L,(((uint64_t)v) << luaL_checkinteger(L,2)) & 0xFFFFFFFFFFFF);
return 1;
}
static int luacall_bitrshift(lua_State *L)
{
lua_check_argc(L,"bitrshift",2);
int64_t v=(int64_t)luaL_checklint(L,1);
if (v>0xFFFFFFFF || v<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
lua_pushlint(L,((uint32_t)v) >> luaL_checkinteger(L,2));
if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
lua_pushlint(L,((uint64_t)v) >> luaL_checkinteger(L,2));
return 1;
}
static int luacall_bitand(lua_State *L)
@@ -86,12 +88,12 @@ static int luacall_bitand(lua_State *L)
lua_check_argc_range(L,"bitand",2,100);
int argc = lua_gettop(L);
int64_t v;
uint32_t sum=0xFFFFFFFF;
uint64_t sum=0xFFFFFFFFFFFF;
for(int i=1;i<=argc;i++)
{
v=(int64_t)luaL_checklint(L,i);
if (v>0xFFFFFFFF || v<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
sum&=(uint32_t)v;
if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
sum&=(uint64_t)v;
}
lua_pushlint(L,sum);
return 1;
@@ -101,33 +103,60 @@ static int luacall_bitor(lua_State *L)
lua_check_argc_range(L,"bitor",1,100);
int argc = lua_gettop(L);
int64_t v;
uint32_t sum=0;
uint64_t sum=0;
for(int i=1;i<=argc;i++)
{
v=(int64_t)luaL_checklint(L,i);
if (v>0xFFFFFFFF || v<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
sum|=(uint32_t)v;
if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
sum|=(uint64_t)v;
}
lua_pushlint(L,sum);
return 1;
}
static int luacall_bitnot(lua_State *L)
static int lua_bitnotx(lua_State *L, int64_t max)
{
lua_check_argc(L,"bitnot",1);
lua_pushlint(L,~(uint32_t)luaL_checklint(L,1));
int64_t v=(int64_t)luaL_checklint(L,1);
if (v>max || v<-max) luaL_error(L, "out of range");
lua_pushlint(L,~(uint64_t)v & max);
return 1;
}
static int luacall_bitnot8(lua_State *L)
{
lua_check_argc(L,"bitnot8",1);
return lua_bitnotx(L, 0xFF);
}
static int luacall_bitnot16(lua_State *L)
{
lua_check_argc(L,"bitnot16",1);
return lua_bitnotx(L, 0xFFFF);
}
static int luacall_bitnot24(lua_State *L)
{
lua_check_argc(L,"bitnot24",1);
return lua_bitnotx(L, 0xFFFFFF);
}
static int luacall_bitnot32(lua_State *L)
{
lua_check_argc(L,"bitnot32",1);
return lua_bitnotx(L, 0xFFFFFFFF);
}
static int luacall_bitnot48(lua_State *L)
{
lua_check_argc(L,"bitnot48",1);
return lua_bitnotx(L, 0xFFFFFFFFFFFF);
}
static int luacall_bitxor(lua_State *L)
{
lua_check_argc_range(L,"bitxor",1,100);
int argc = lua_gettop(L);
int64_t v;
uint32_t sum=0;
uint64_t sum=0;
for(int i=1;i<=argc;i++)
{
v=(int64_t)luaL_checklint(L,i);
if (v>0xFFFFFFFF || v<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
sum^=(uint32_t)v;
if (v>0xFFFFFFFFFFFF || v<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
sum^=(uint64_t)v;
}
lua_pushlint(L,sum);
return 1;
@@ -137,11 +166,11 @@ static int luacall_bitget(lua_State *L)
lua_check_argc(L,"bitget",3);
int64_t iwhat = (int64_t)luaL_checklint(L,1);
if (iwhat>0xFFFFFFFF || iwhat<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
uint32_t what = (uint32_t)iwhat;
if (iwhat>0xFFFFFFFFFFFF || iwhat<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
uint64_t what = (uint64_t)iwhat;
lua_Integer from = luaL_checkinteger(L,2);
lua_Integer to = luaL_checkinteger(L,3);
if (from>to || from>31 || to>31)
if (from>to || from>47 || to>47)
luaL_error(L, "bit range invalid");
what = (what >> from) & ~((lua_Integer)-1 << (to-from+1));
@@ -154,14 +183,14 @@ static int luacall_bitset(lua_State *L)
lua_check_argc(L,"bitset",4);
int64_t iwhat = (int64_t)luaL_checklint(L,1);
if (iwhat>0xFFFFFFFF || iwhat<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
uint32_t what = (uint32_t)iwhat;
if (iwhat>0xFFFFFFFFFFFF || iwhat<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
uint64_t what = (uint64_t)iwhat;
lua_Integer from = luaL_checkinteger(L,2);
lua_Integer to = luaL_checkinteger(L,3);
int64_t iset = (int64_t)luaL_checklint(L,4);
if (iset>0xFFFFFFFF || iset<-(int64_t)0xFFFFFFFF) luaL_error(L, "out of range");
uint32_t set = (uint32_t)iset;
if (from>to || from>31 || to>31)
if (iset>0xFFFFFFFFFFFF || iset<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
uint64_t set = (uint64_t)iset;
if (from>to || from>47 || to>47)
luaL_error(L, "bit range invalid");
lua_Integer mask = ~((lua_Integer)-1 << (to-from+1));
@@ -229,6 +258,20 @@ static int luacall_u32(lua_State *L)
lua_pushlint(L,pntoh32(p+offset));
return 1;
}
static int luacall_u48(lua_State *L)
{
lua_check_argc_range(L,"u48",1,2);
int argc=lua_gettop(L);
size_t l;
lua_Integer offset;
const uint8_t *p = (uint8_t*)luaL_checklstring(L,1,&l);
offset = (argc>=2 && lua_type(L,2)!=LUA_TNIL) ? luaL_checkinteger(L,2)-1 : 0;
if (offset<0 || (offset+6)>l) luaL_error(L, "out of range");
lua_pushlint(L,pntoh48(p+offset));
return 1;
}
static int luacall_swap16(lua_State *L)
{
lua_check_argc(L,"swap16",1);
@@ -236,8 +279,17 @@ static int luacall_swap16(lua_State *L)
int64_t i = (int64_t)luaL_checklint(L,1);
if (i>0xFFFF || i<-(int64_t)0xFFFF) luaL_error(L, "out of range");
uint16_t u = (uint16_t)i;
// __builtin_bswap16 is absent in ancient lexra gcc 4.6
lua_pushinteger(L,(u>>8) | ((u&0xFF)<<8));
lua_pushinteger(L,swap16(u));
return 1;
}
static int luacall_swap24(lua_State *L)
{
lua_check_argc(L,"swap24",1);
int64_t i =(int64_t)luaL_checklint(L,1);
if (i>0xFFFFFF || i<-(int64_t)0xFFFFFF) luaL_error(L, "out of range");
uint32_t u = (uint32_t)i;
lua_pushlint(L,swap24(u));
return 1;
}
static int luacall_swap32(lua_State *L)
@@ -250,16 +302,26 @@ static int luacall_swap32(lua_State *L)
lua_pushlint(L,__builtin_bswap32(u));
return 1;
}
static int lua_uxadd(lua_State *L, uint32_t max)
static int luacall_swap48(lua_State *L)
{
lua_check_argc(L,"swap48",1);
int64_t i =(int64_t)luaL_checklint(L,1);
if (i>0xFFFFFFFFFFFF || i<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
uint64_t u = (uint64_t)i;
lua_pushlint(L, swap48(u));
return 1;
}
static int lua_uxadd(lua_State *L, int64_t max)
{
int64_t v;
uint32_t sum=0;
uint64_t sum=0;
int argc = lua_gettop(L);
for(int i=1;i<=argc;i++)
{
v = (int64_t)luaL_checklint(L,i);
if (v>max || v<-(int64_t)max) luaL_error(L, "out of range");
sum+=(uint32_t)v;
if (v>max || v<-max) luaL_error(L, "out of range");
sum+=(uint64_t)v;
}
lua_pushlint(L, sum & max);
return 1;
@@ -284,6 +346,11 @@ static int luacall_u32add(lua_State *L)
lua_check_argc_range(L,"u32add",1,100);
return lua_uxadd(L, 0xFFFFFFFF);
}
static int luacall_u48add(lua_State *L)
{
lua_check_argc_range(L,"u48add",1,100);
return lua_uxadd(L, 0xFFFFFFFFFFFF);
}
static int luacall_bu8(lua_State *L)
{
@@ -328,6 +395,17 @@ static int luacall_bu32(lua_State *L)
lua_pushlstring(L,(char*)v,4);
return 1;
}
static int luacall_bu48(lua_State *L)
{
lua_check_argc(L,"bu48",1);
int64_t i = (int64_t)luaL_checklint(L,1);
if (i>0xFFFFFFFFFFFF || i<-(int64_t)0xFFFFFFFFFFFF) luaL_error(L, "out of range");
uint8_t v[4];
phton48(v,(uint64_t)i);
lua_pushlstring(L,(char*)v,6);
return 1;
}
static int luacall_divint(lua_State *L)
{
@@ -412,7 +490,7 @@ static int luacall_parse_hex(lua_State *L)
LUA_STACK_GUARD_ENTER(L)
size_t l;
const char *hex = lua_tolstring(L,1,&l);
const char *hex = luaL_checklstring(L,1,&l);
if ((l&1)) goto err;
l>>=1;
uint8_t *p = malloc(l);
@@ -690,6 +768,22 @@ static int luacall_clock_gettime(lua_State *L)
}
LUA_STACK_GUARD_RETURN(L,2)
}
static t_lua_desync_context *lua_desync_ctx()
{
if (lua_isnil(params.L,1))
luaL_error(params.L, "missing ctx");
if (!lua_islightuserdata(params.L,1))
luaL_error(params.L, "bad ctx - invalid data type");
t_lua_desync_context *ctx = lua_touserdata(params.L,1);
// ensure it's really ctx. LUA could pass us any lightuserdata pointer
if (ctx->magic!=MAGIC_CTX)
luaL_error(params.L, "bad ctx - magic bytes invalid");
return ctx;
}
static int luacall_instance_cutoff(lua_State *L)
{
// out : instance_name.profile_number[0]
@@ -699,16 +793,12 @@ static int luacall_instance_cutoff(lua_State *L)
LUA_STACK_GUARD_ENTER(L)
const t_lua_desync_context *ctx;
if (lua_isnil(L,1))
// this can happen in orchestrated function. they do not have their own ctx and they cant cutoff
DLOG("instance cutoff not possible because missing ctx\n");
else
{
if (!lua_islightuserdata(L,1))
luaL_error(L, "instance_cutoff expect desync context in the first argument");
ctx = lua_touserdata(L,1);
const t_lua_desync_context *ctx = lua_desync_ctx();
int argc=lua_gettop(L);
bool bIn,bOut;
@@ -720,7 +810,6 @@ static int luacall_instance_cutoff(lua_State *L)
}
else
bIn = bOut = true;
if (ctx->ctrack)
{
DLOG("instance cutoff for '%s' in=%u out=%u\n",ctx->instance,bIn,bOut);
@@ -785,11 +874,7 @@ static int luacall_lua_cutoff(lua_State *L)
LUA_STACK_GUARD_ENTER(L)
t_lua_desync_context *ctx;
if (!lua_islightuserdata(L,1))
luaL_error(L, "lua_cutoff expect desync context in the first argument");
ctx = lua_touserdata(L,1);
t_lua_desync_context *ctx = lua_desync_ctx();
int argc=lua_gettop(L);
bool bIn,bOut;
@@ -821,11 +906,7 @@ static int luacall_execution_plan(lua_State *L)
LUA_STACK_GUARD_ENTER(L)
const t_lua_desync_context *ctx;
if (!lua_islightuserdata(L,1))
luaL_error(L, "execution_plan expect desync context in the first argument");
ctx = lua_touserdata(L,1);
t_lua_desync_context *ctx = lua_desync_ctx();
lua_newtable(L);
@@ -862,11 +943,7 @@ static int luacall_execution_plan_cancel(lua_State *L)
{
lua_check_argc(L,"execution_plan_cancel",1);
t_lua_desync_context *ctx;
if (!lua_islightuserdata(L,1))
luaL_error(L, "execution_plan_cancel expect desync context in the first argument");
ctx = lua_touserdata(L,1);
t_lua_desync_context *ctx = lua_desync_ctx();
DLOG("execution plan cancel from '%s'\n",ctx->instance);
@@ -881,11 +958,7 @@ static int luacall_raw_packet(lua_State *L)
LUA_STACK_GUARD_ENTER(L)
const t_lua_desync_context *ctx;
if (!lua_islightuserdata(L,1))
luaL_error(L, "raw_packet expect desync context in the first argument");
ctx = lua_touserdata(L,1);
const t_lua_desync_context *ctx = lua_desync_ctx();
lua_pushlstring(L, (const char*)ctx->dis->data_pkt, ctx->dis->len_pkt);
@@ -1251,13 +1324,15 @@ void lua_push_dissect(const struct dissect *dis)
if (dis)
{
lua_createtable(params.L, 0, 7);
lua_createtable(params.L, 0, 9);
lua_pushf_iphdr(dis->ip, dis->len_l3);
lua_pushf_ip6hdr(dis->ip6, dis->len_l3);
lua_pushf_tcphdr(dis->tcp, dis->len_l4);
lua_pushf_udphdr(dis->udp, dis->len_l4);
lua_pushf_int("l4proto",dis->proto);
lua_pushf_int("transport_len",dis->transport_len);
lua_pushf_int("l3_len",dis->len_l3);
lua_pushf_int("l4_len",dis->len_l4);
lua_pushf_raw("payload",dis->data_payload,dis->len_payload);
}
else
@@ -1279,13 +1354,15 @@ void lua_pushf_ctrack_pos(const t_ctrack *ctrack, const t_ctrack_position *pos)
lua_pushf_lint("pcounter", pos->pcounter);
lua_pushf_lint("pdcounter", pos->pdcounter);
lua_pushf_lint("pbcounter", pos->pbcounter);
if (pos->ip6flow) lua_pushf_int("ip6_flow", pos->ip6flow);
if (ctrack->ipproto == IPPROTO_TCP)
{
lua_pushliteral(params.L, "tcp");
lua_createtable(params.L, 0, 10);
lua_createtable(params.L, 0, 11);
lua_pushf_lint("seq0", pos->seq0);
lua_pushf_lint("seq", pos->seq_last);
lua_pushf_lint("rseq", pos->seq_last - pos->seq0);
lua_pushf_bool("rseq_over_2G", pos->rseq_over_2G);
lua_pushf_int("pos", pos->pos - pos->seq0);
lua_pushf_int("uppos", pos->uppos - pos->seq0);
lua_pushf_int("uppos_prev", pos->uppos_prev - pos->seq0);
@@ -1660,7 +1737,7 @@ bool lua_reconstruct_iphdr(int idx, struct ip *ip, size_t *len)
if (lua_type(params.L,-1)==LUA_TSTRING)
{
p = lua_tolstring(params.L,-1,&lopt);
if (lopt)
if (p && lopt)
{
if (lopt>40 || ((sizeof(struct ip) + ((lopt+3)&~3)) > *len)) goto err;
memcpy(ip+1,p,lopt);
@@ -1992,7 +2069,7 @@ bool lua_reconstruct_dissect(int idx, uint8_t *buf, size_t *len, bool badsum, bo
lua_getfield(params.L,idx,"payload");
p = lua_tolstring(params.L,-1,&lpayload);
if (lpayload)
if (p && lpayload)
{
if (left<lpayload) goto err;
memcpy(data,p,lpayload);
@@ -2135,7 +2212,7 @@ static int luacall_csum_ip4_fix(lua_State *L)
}
static int luacall_csum_tcp_fix(lua_State *L)
{
// csum_ip4_fix(ip_header, tcp_header, payload) returns tcp_header
// csum_tcp_fix(ip_header, tcp_header, payload) returns tcp_header
lua_check_argc(L,"csum_tcp_fix",3);
LUA_STACK_GUARD_ENTER(L)
@@ -2176,7 +2253,7 @@ static int luacall_csum_tcp_fix(lua_State *L)
}
static int luacall_csum_udp_fix(lua_State *L)
{
// csum_ip4_fix(ip_header, tcp_header, payload) returns tcp_header
// csum_udp_fix(ip_header, udp_header, payload) returns udp_header
lua_check_argc(L,"csum_udp_fix",3);
LUA_STACK_GUARD_ENTER(L)
@@ -2823,20 +2900,80 @@ static bool lua_desync_functions_exist()
return true;
}
static bool lua_file_open_test(const char *filename, bool *b_gzip, char *fname)
{
FILE *F = fopen(filename,"rb");
if (F)
{
if (fname) snprintf(fname,PATH_MAX,"%s",filename);
}
else
{
size_t l = strlen(filename);
char *fngz = malloc(l+4);
if (!fngz) return false;
memcpy(fngz, filename, l);
memcpy(fngz+l,".gz",4);
if (fname) snprintf(fname,PATH_MAX,"%s",fngz);
F = fopen(fngz,"rb");
free(fngz);
}
if (F)
{
if (b_gzip) *b_gzip = is_gzip(F);
fclose(F);
}
return !!F;
}
bool lua_test_init_script_files(void)
{
struct str_list *str;
LIST_FOREACH(str, &params.lua_init_scripts, next)
{
if (str->str[0]=='@' && !file_open_test(str->str+1, O_RDONLY))
if (str->str[0]=='@' && !lua_file_open_test(str->str+1, NULL, NULL))
{
DLOG_ERR("LUA file '%s' not accessible\n",str->str+1);
#ifndef __CYGWIN__
int e = errno;
#endif
DLOG_ERR("LUA file '%s' or '%s.gz' not accessible\n", str->str+1, str->str+1);
#ifndef __CYGWIN__
if (e==EACCES)
DLOG_ERR("I drop my privileges and do not run Lua as root\ncheck file permissions and +x rights on all directories in the path\n");
#endif
return false;
}
}
return true;
}
static int luaL_doZfile(lua_State *L, const char *filename)
{
bool b_gzip;
char fname[PATH_MAX];
if (!lua_file_open_test(filename, &b_gzip, fname))
luaL_error(L, "could not open lua file '%s' or '%s.gz'", filename, filename);
if (b_gzip)
{
size_t size;
char *buf;
int r;
FILE *F = fopen(fname, "rb");
if (!F)
luaL_error(L, "could not open lua file '%s'", fname);
r = z_readfile(F, &buf, &size, 1);
fclose(F);
if (r != Z_OK)
luaL_error(L, "could not unzip lua file '%s'", fname);
buf[size] = 0;
r = luaL_dostring(L, buf);
free(buf);
return r;
}
else
return luaL_dofile(L, filename);
}
static bool lua_init_scripts(void)
{
struct str_list *str;
@@ -2855,7 +2992,7 @@ static bool lua_init_scripts(void)
DLOG("LUA RUN STR: %s\n",s);
}
}
if ((status = str->str[0]=='@' ? luaL_dofile(params.L, str->str+1) : luaL_dostring(params.L, str->str)))
if ((status = str->str[0]=='@' ? luaL_doZfile(params.L, str->str+1) : luaL_dostring(params.L, str->str)))
{
lua_perror(params.L);
return false;
@@ -3000,10 +3137,14 @@ static void lua_init_const(void)
{"IP_OFFMASK",IP_OFFMASK},
{"IP_FLAGMASK",IP_RF|IP_DF|IP_MF},
{"IPTOS_ECN_MASK",IPTOS_ECN_MASK},
{"IPTOS_ECN_NOT_ECT",0},
{"IPTOS_ECN_ECT1",IPTOS_ECN_ECT1},
{"IPTOS_ECN_ECT0",IPTOS_ECN_ECT0},
{"IPTOS_ECN_CE",IPTOS_ECN_CE},
{"IPTOS_DSCP_MASK",0xF0},
{"IP6F_MORE_FRAG",0x0001}, // in ip6.h it's defined depending of machine byte order
{"IPV6_FLOWLABEL_MASK",0x000FFFFF},
{"IPV6_FLOWINFO_MASK",0x0FFFFFFF},
{"IPPROTO_IP",IPPROTO_IP},
{"IPPROTO_IPV6",IPPROTO_IPV6},
@@ -3079,10 +3220,14 @@ static void lua_init_functions(void)
{"bitand",luacall_bitand},
{"bitor",luacall_bitor},
{"bitxor",luacall_bitxor},
{"bitxor",luacall_bitxor},
{"bitget",luacall_bitget},
{"bitset",luacall_bitset},
{"bitnot",luacall_bitnot},
{"bitnot",luacall_bitnot48},
{"bitnot8",luacall_bitnot8},
{"bitnot16",luacall_bitnot16},
{"bitnot24",luacall_bitnot24},
{"bitnot32",luacall_bitnot32},
{"bitnot48",luacall_bitnot48},
// WARNING : lua 5.1 and luajit does not correctly implement integers. they seem to be stored as float which can't hold 64-bit.
// convert part of the blob (string) to number
@@ -3090,19 +3235,24 @@ static void lua_init_functions(void)
{"u16",luacall_u16},
{"u24",luacall_u24},
{"u32",luacall_u32},
{"u48",luacall_u48},
// add any number of arguments as they would be unsigned int of specific size
{"u8add",luacall_u8add},
{"u16add",luacall_u16add},
{"u24add",luacall_u24add},
{"u32add",luacall_u32add},
{"u48add",luacall_u48add},
// convert number to blob (string) - big endian
{"bu8",luacall_bu8},
{"bu16",luacall_bu16},
{"bu24",luacall_bu24},
{"bu32",luacall_bu32},
{"bu48",luacall_bu48},
// swap byte order
{"swap16",luacall_swap16},
{"swap24",luacall_swap24},
{"swap32",luacall_swap32},
{"swap48",luacall_swap48},
// integer division
{"divint",luacall_divint},

View File

@@ -101,7 +101,9 @@ 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);
#define MAGIC_CTX 0xE73DC935
typedef struct {
uint32_t magic;
unsigned int func_n;
const char *func, *instance;
const struct desync_profile *dp;

View File

@@ -538,7 +538,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:
@@ -630,6 +630,7 @@ static int win_main()
{
res=w_win32_error; goto ex;
}
if (!win_sandbox())
{
res=w_win32_error;
@@ -637,7 +638,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())
{
@@ -726,6 +726,7 @@ ex:
static void exit_clean(int code)
{
cleanup_params(&params);
exit(code);
}
@@ -1406,7 +1407,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"
@@ -1435,6 +1436,7 @@ static void exithelp(void)
" --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"
@@ -1553,6 +1555,7 @@ enum opt_indices {
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,
@@ -1641,6 +1644,7 @@ static const struct option long_options[] = {
[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},
@@ -1812,6 +1816,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;
}
@@ -2098,6 +2103,9 @@ int main(int argc, char **argv)
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;

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 3
#define LUA_COMPAT_VER 4

View File

@@ -350,6 +350,7 @@ void dp_init(struct desync_profile *dp)
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;

View File

@@ -84,6 +84,7 @@ struct desync_profile
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;

View File

@@ -138,13 +138,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 +248,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 +290,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 +324,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 +353,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 +619,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",
@@ -458,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)
{
@@ -1310,9 +1317,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;
@@ -1323,8 +1330,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
@@ -1342,8 +1349,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;
}
@@ -1401,7 +1407,11 @@ bool IsWireguardKeepalive(const uint8_t *data, size_t len)
}
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)
{
@@ -1445,3 +1455,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,
@@ -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,
@@ -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 {