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

393 Commits
v0.6.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
bol-van
0aac2965c1 nfqws2: minor reorder struct members 2025-12-13 22:13:04 +03:00
bol-van
d1128a8bc6 update docs 2025-12-13 20:56:17 +03:00
bol-van
e016fc0e42 update docs 2025-12-13 20:55:50 +03:00
bol-van
f48ea2f6a7 update docs 2025-12-13 20:39:03 +03:00
bol-van
2ab71ab895 update docs 2025-12-13 20:19:02 +03:00
bol-van
736e0ba3d4 update docs 2025-12-13 20:16:13 +03:00
bol-van
f2ae880c11 update docs 2025-12-13 20:15:05 +03:00
bol-van
019f3089c6 update docs 2025-12-13 20:09:12 +03:00
bol-van
30d28488c9 update docs 2025-12-13 19:53:54 +03:00
bol-van
5bcec4aada update docs 2025-12-13 19:50:16 +03:00
bol-van
886fbabcfc update docs 2025-12-13 17:00:17 +03:00
bol-van
cd8dbf2a2b update docs 2025-12-13 16:59:05 +03:00
bol-van
002742bd03 update docs 2025-12-13 16:56:45 +03:00
bol-van
dc2c707c3c update docs 2025-12-13 16:55:22 +03:00
bol-van
9630d0a9df update docs 2025-12-13 16:54:54 +03:00
bol-van
f4c4d5e558 update docs 2025-12-13 16:43:11 +03:00
bol-van
7b37880954 update docs 2025-12-13 16:39:53 +03:00
bol-van
6b7738ac16 update docs 2025-12-13 16:38:46 +03:00
bol-van
8dec014b50 update docs 2025-12-13 16:36:46 +03:00
bol-van
b0ee32f3dc update docs 2025-12-13 16:36:21 +03:00
bol-van
0e770ff46d update docs 2025-12-13 16:35:52 +03:00
bol-van
14b3aef030 update docs 2025-12-13 16:33:05 +03:00
bol-van
004c583595 update docs 2025-12-13 16:31:18 +03:00
bol-van
c4818a6a32 nfqws2: solved inability to get SSID using nl80211 on kernels 5.19+ 2025-12-13 15:33:57 +03:00
bol-van
58d57fed01 update docs 2025-12-13 11:27:16 +03:00
bol-van
d6b73fe7e0 update docs 2025-12-13 11:26:58 +03:00
bol-van
4867838fce update docs 2025-12-13 11:24:35 +03:00
bol-van
4b2551509f update docs 2025-12-13 11:22:16 +03:00
bol-van
ed6acb36a1 nfqws2: update docs 2025-12-12 23:45:32 +03:00
bol-van
26b80e80b6 nfqws2: update docs 2025-12-12 23:43:47 +03:00
bol-van
79b776b5a9 nfqws2: update docs 2025-12-12 23:42:27 +03:00
bol-van
3b251b9ee6 nfqws2: update docs 2025-12-12 23:41:43 +03:00
bol-van
8c65a966d9 nfqws2: update docs 2025-12-12 23:40:58 +03:00
bol-van
9da0b13aa3 nfqws2: update docs 2025-12-12 23:39:18 +03:00
bol-van
d7fd491121 nfqws2: update docs 2025-12-12 23:38:09 +03:00
bol-van
c60ef399ec nfqws2: update docs 2025-12-12 23:36:15 +03:00
bol-van
2abab21e4b nfqws2: update docs 2025-12-12 23:31:17 +03:00
bol-van
6190babb99 nfqws2: update docs 2025-12-12 23:29:55 +03:00
bol-van
7ce0b4a996 nfqws2: reduce default retrans maxseq to 32768, adjust config 2025-12-12 23:28:49 +03:00
bol-van
053556fe2d nfqws2: autohostlist reset fail counter if udp_in > threshold 2025-12-12 23:11:11 +03:00
bol-van
52571045fe nfqws2: add EOL at the end of truncated buffered DLOG line if it's too large. increase log line buffer 2025-12-12 20:37:58 +03:00
bol-van
db875ed1d4 nfqws2: cancel reasm if server window size is smaller than expected reasm size 2025-12-12 20:20:12 +03:00
bol-van
e828864811 nfqws2: cancel reasm if server window size is smaller than expected reasm size 2025-12-12 20:18:55 +03:00
bol-van
4404127fa3 update docs 2025-12-12 18:26:30 +03:00
bol-van
13e81e4b6f update docs 2025-12-12 18:25:45 +03:00
bol-van
a631add2d9 update docs 2025-12-12 18:24:34 +03:00
bol-van
26b9b63a20 update docs 2025-12-12 18:21:35 +03:00
bol-van
90489fad2f update docs 2025-12-12 18:21:17 +03:00
bol-van
d93c243d21 update docs 2025-12-12 18:20:46 +03:00
bol-van
65235d71d7 update docs 2025-12-12 18:19:53 +03:00
bol-van
fc01e6715f update docs 2025-12-12 18:04:18 +03:00
bol-van
1a33d68998 update docs 2025-12-12 18:00:57 +03:00
bol-van
dfaa475d2a update docs 2025-12-12 17:50:42 +03:00
bol-van
743018423a update docs 2025-12-12 17:47:15 +03:00
bol-van
762023f201 update docs 2025-12-12 16:45:16 +03:00
bol-van
a296b93b7a update docs 2025-12-12 16:44:17 +03:00
bol-van
1c9b3aa1bc update docs 2025-12-12 16:40:02 +03:00
bol-van
565fa8e337 init.d: fix non-working incoming redirect 2025-12-12 16:09:31 +03:00
bol-van
9fcecd07d1 update docs 2025-12-12 12:19:04 +03:00
bol-van
652e271877 update docs 2025-12-12 12:06:55 +03:00
bol-van
fc7ed4f4a8 update docs 2025-12-12 12:04:57 +03:00
bol-van
e9e5bdc860 update docs 2025-12-12 12:04:31 +03:00
bol-van
a2b8300219 update docs 2025-12-12 12:03:45 +03:00
bol-van
dfdcfbdf51 update docs 2025-12-12 12:02:12 +03:00
bol-van
170ec372fb update docs 2025-12-12 12:00:53 +03:00
bol-van
3f073908a6 update docs 2025-12-12 11:59:17 +03:00
bol-van
7708021587 nfqws2: rewrite autohostlist udp failure detector logic 2025-12-11 15:19:31 +03:00
bol-van
912aadf6ca zapret-auto: override host autostate key 2025-12-11 13:41:04 +03:00
bol-van
420cc0c3ef nfqws2: fix crash 2025-12-11 13:38:10 +03:00
bol-van
6ce5829d06 zapret-auto: override host autostate key 2025-12-11 12:57:32 +03:00
bol-van
a6d43af931 nfqws2: autohostlist do not react to rseq 0 2025-12-11 01:03:25 +03:00
bol-van
ca9898959e nfqws2: remove commented test code 2025-12-11 00:23:20 +03:00
bol-van
8cd2904614 nfqws2: push desync.track.pos.dt as float with nsec accuracy 2025-12-11 00:21:22 +03:00
bol-van
0de1ab1b1b init.d: AUTOHOSTLIST_INCOMING_MAXSEQ 2025-12-10 23:21:30 +03:00
bol-van
d1690aadcf nfqws2: autohostlist incoming failure triggers change 2025-12-10 23:11:28 +03:00
bol-van
2dd8533fb5 nfqws2,zapret-lib.lua,zapret-auto.lua: restructure conntrack record 2025-12-10 19:36:31 +03:00
bol-van
33ac18ea6b zapret-lib,zapret-auto: do not use desync copy to not lose VERDICT_MODIFY changes 2025-12-10 13:43:39 +03:00
bol-van
5c05c10f83 zapret-lib: return 0 if #val refers to non-string and non-table type 2025-12-10 10:49:46 +03:00
bol-van
7de0995d4a nfqws2,zapret-lib: fix non-working # and % arg subst under orchestrator 2025-12-10 10:28:48 +03:00
bol-van
a1c64e4dea update doc 2025-12-09 18:08:36 +03:00
bol-van
92b66b1535 update doc 2025-12-09 18:08:01 +03:00
bol-van
9bf4fb11e7 update doc 2025-12-09 18:05:08 +03:00
bol-van
7deeb04207 start writing manual.md 2025-12-09 18:00:24 +03:00
74 changed files with 8208 additions and 1326 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 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,11 +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="--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}"
parmNA="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm9:+ $parm9}"
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

@@ -97,17 +97,19 @@ nft_activate_chain4()
{
# $1 - chain name
# $2 - saddr/daddr
local b rule markf= act
local b rule markf= act flt_ifname
[ "$DISABLE_IPV4" = "1" ] || {
eval act="\$${1}_act4"
[ -n "$act" ] && return
b=0
nft_wanif_filter_present && b=1
flt_ifname="oifname"
starts_with "$1" pre && flt_ifname="iifname"
[ "$2" = daddr ] && markf=$(nft_mark_filter)
rule="meta mark and $DESYNC_MARK == 0 $markf"
[ $b = 1 ] && rule="$rule oifname @wanif"
[ $b = 1 ] && rule="$rule $flt_ifname @wanif"
rule="$rule ip $2 != @nozapret jump $1"
nft_rule_exists ${1}_hook "$rule" || nft_add_rule ${1}_hook $rule
@@ -118,17 +120,19 @@ nft_activate_chain6()
{
# $1 - chain name
# $2 - saddr/daddr
local b rule markf=
local b rule markf= act flt_ifname
[ "$DISABLE_IPV6" = "1" ] || {
eval act="\$${1}_act6"
[ -n "$act" ] && return
b=0
nft_wanif6_filter_present && b=1
flt_ifname="oifname"
starts_with "$1" pre && flt_ifname="iifname"
[ "$2" = daddr ] && markf=$(nft_mark_filter)
rule="meta mark and $DESYNC_MARK == 0 $markf"
[ $b = 1 ] && rule="$rule oifname @wanif6"
[ $b = 1 ] && rule="$rule $flt_ifname @wanif6"
rule="$rule ip6 $2 != @nozapret6 jump $1"
nft_rule_exists ${1}_hook "$rule" || nft_add_rule ${1}_hook $rule

View File

@@ -26,10 +26,16 @@ IPSET_OPT="hashsize 262144 maxelem $SET_MAXELEM"
IP2NET_OPT4="--prefix-length=22-30 --v4-threshold=3/4"
IP2NET_OPT6="--prefix-length=56-64 --v6-threshold=5"
# options for auto hostlist
AUTOHOSTLIST_RETRANS_MAXSEQ=65536
# NOTE : in order for these adjustment to work it's required to redirect enough starting packets
# NOTE : set PKT_IN, PKT_OUT variables appropriately
AUTOHOSTLIST_INCOMING_MAXSEQ=4096
AUTOHOSTLIST_RETRANS_MAXSEQ=32768
AUTOHOSTLIST_RETRANS_RESET=1
AUTOHOSTLIST_RETRANS_THRESHOLD=3
AUTOHOSTLIST_FAIL_THRESHOLD=3
AUTOHOSTLIST_FAIL_TIME=60
AUTOHOSTLIST_UDP_IN=1
AUTOHOSTLIST_UDP_OUT=4
# 1 = debug autohostlist positives to ipset/zapret-hosts-auto-debug.log
AUTOHOSTLIST_DEBUGLOG=0
@@ -61,11 +67,10 @@ NFQWS2_PORTS_TCP=80,443
NFQWS2_PORTS_UDP=443
# PKT_OUT means connbytes dir original
# PKT_IN means connbytes dir reply
# this is --dpi-desync-cutoff=nX kernel mode implementation for linux. it saves a lot of CPU.
NFQWS2_TCP_PKT_OUT=$((6+$AUTOHOSTLIST_RETRANS_THRESHOLD))
NFQWS2_TCP_PKT_IN=3
NFQWS2_UDP_PKT_OUT=$((6+$AUTOHOSTLIST_RETRANS_THRESHOLD))
NFQWS2_UDP_PKT_IN=0
NFQWS2_TCP_PKT_OUT=20
NFQWS2_TCP_PKT_IN=10
NFQWS2_UDP_PKT_OUT=5
NFQWS2_UDP_PKT_IN=3
# redirect outgoing traffic without connbytes limiter and incoming with connbytes limiter
# normally it's needed only for stateless DPI that matches every packet in a single TCP session
# typical example are plain HTTP keep alives
@@ -93,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

@@ -80,3 +80,67 @@ v0.6.1
* zapret-lib, zapret-auto: condition and stopif orchestrators
* zapret-lib: detect_payload_str - sample lua payload detector
* blockcheck2: unterminated string fix
v0.7
* nfqws2, zapret-lib : fix non-working % and # arg substitution under orchestrator
* nfqws2, zapret-lib : structure conntrack in/out positions. pass in desync.track.pos.{client,server,direct,reverse} position tables
* nfqws2: autohostlist: trigger RST and http redirect failures only within specified relative sequence
* nfqws2: autohostlist: trigger http redirect failure if payload is http_req without connection proto check
* nfqws2: push desync.track.pos.dt as float with nsec accuracy
* zapret-auto: override host autostate key in automate_host_record
* nfqws2: rewrite udp autohostlist failure detector logic
v0.7.1
* init.d: nft fix non-working incoming redirect
* nfqws2: cancel reasm if server window size is smaller than expected reasm size
* nfqws2: add EOL at the end of truncated buffered DLOG line if it's too large. increase log line buffer
* nfqws2: autohostlist reset fail counter if udp_in > threshold
* nfqws2: reduced default retrans maxseq to 32768
* nfqws2: solved inability to get SSID using nl80211 on kernels 5.19+
v0.7.2
* zapret-lib: fix broken is_retransmission()
* zapret-auto: add success detector logic
* nfqws2: clean lua cutoff on profile change
* zapret-auto: separate hostkey function
v0.7.4
* nfqws2, zapret-lib : check tcp sequence range overflow
* zapret-lib: seq compare functions
* nfqws2: add l3_len, l4_len to dissect
* nfqws2: fix broken l7proto profile rediscovery
* winws2: harden sandbox. disable child process execution , some UI interaction and desktop settings change
v0.7.5
* zapret-auto: orchestrator "repeater"
* blockcheck2: check http3 with ipv6 exthdr
* github actions: separate target arm-old with LUA classic, not JIT
* zapret-auto: iff/neg in repeater
* zapret-antidpi: multidisorder_legacy
* ipset: remove get_reestr_hostlist.sh and get_reestr_resolve.sh because zapret-info does not and will probably not ever update
* nfqws2: fix "reasm cancelled" if no incoming traffic redirected
* blockcheck2: MULTIDISORDER=multidisorder_legacy
v0.7.6
* nfqws2: reevaluate profile on l7/host discovery in any direction
* nfqws2: dtls protocol detection
* nfqws2: autohostlist reset retransmitter to break long wait
* zapret-auto: stadard_failure_detector reset retransmitter to break long wait
* nfqws2, init.d, windivert : dht and wg detection changes
v0.8.0
* init.d: 50-dht4all NFQWS_OPT_DHT_PKT_OUT
* nfqws2: (LUA_COMPAT_VER=4) support 48-bit arithmetics
* github actions: remove arm-old target - luajit fail reason revealed
* nfqws2: do not treat quic handshake messages as initials
* zapret-lib: tls dissector/reconstructor
* zapret-antidpi: tls_client_hello_clone
* zapret-antidpi: "optional" arg to blob taking functions
* nfqws2: support gzipped lua file. auto use script.lua.gz

View File

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

5063
docs/manual.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,3 @@
# zapret2 v0.2
## Зачем это нужно
Автономное средство противодействия DPI, которое не требует подключения каких-либо сторонних серверов. Может помочь
@@ -10,6 +8,20 @@ VPN. Может использоваться для частичной проз
традиционные Linux-системы, FreeBSD, OpenBSD, Windows. В некоторых случаях возможна самостоятельная прикрутка
решения к различным прошивкам.
[Полный мануал](manual.md)
## Поддержать разработчика
Если вы считаете проект полезным и желаете поддержать разработку, направляйте ваши пожертвования на следующие адреса криптокошельков :
USDT `0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E` (предпочительно сеть ERC-20)
BTC `bc1qhqew3mrvp47uk2vevt5sctp7p2x9m7m5kkchve`
ETH `0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E`
## Чем это отличается от zapret1
zapret2 является дальнейшим развитием проекта zapret.
@@ -24,12 +36,12 @@ zapret2 является дальнейшим развитием проекта
или хотя бы область , в которой их можно искать, плюс владеющий базовыми навыками программирования.
*nfqws2* оставляет в себе практически тот же функционал - распознавание протоколов, реассемблинг, дешифровка, управление профилями, хостлисты, ipset-ы, базовая фильтрация.
Но он полностью лишается возможностей самостоятельно воздействовать на трафик. Часть "дурения" переносится в скриптовой язык программирования LUA.
Но он полностью лишается возможностей самостоятельно воздействовать на трафик. Часть "дурения" переносится в скриптовой язык программирования Lua.
LUA код получает от C кода структурированное представление приходящих пакетов в виде дерева (диссекты), подобного тем, что вы видите в wireshark.
Lua код получает от C кода структурированное представление приходящих пакетов в виде дерева (диссекты), подобного тем, что вы видите в wireshark.
Туда же приходят результаты сборки или дешифровки частей некоторых протоколов (tls, quic).
С код предоставляет функции-хелперы, позволяющие отсылать пакеты, работать с двоичными данными, разбирать TLS, искать маркер-позции и т.д.
Имеется библиотека хелперов, написанных на LUA, а так же готовая библиотека программ атаки на DPI (стратегий), реализующая функции *nfqws1* в расширенном варианте
Имеется библиотека хелперов, написанных на Lua, а так же готовая библиотека программ атаки на DPI (стратегий), реализующая функции *nfqws1* в расширенном варианте
и с большей гибкостью.
Вы всегда сможете взять и дописать что-то свое. В этом и есть смысл, чтобы борьбой с DPI смог заняться любой, кто разбирается в пакетах.
@@ -40,8 +52,8 @@ zapret2 - инструмент для таких энтузиастов. Но э
## С чего начать
Хотелось бы избежать "талмуда" на главной странице. Поэтому начнем со способа запуска *nfqws2* и описания способов портирования стратегий *nfqws1* - как в *nfqws2* сделать то же самое, что можно было в *nfqws1*.
Когда вы поймете как это работает, вы можете посмотреть LUA код, находящийся "под капотом". Разобрать как он работает, попробовать написать что-то свое.
Хотелось бы избежать [талмуда](manual.md) на главной странице. Поэтому начнем со способа запуска *nfqws2* и описания способов портирования стратегий *nfqws1* - как в *nfqws2* сделать то же самое, что можно было в *nfqws1*.
Когда вы поймете как это работает, вы можете посмотреть Lua код, находящийся "под капотом". Разобрать как он работает, попробовать написать что-то свое.
"талмуд" обязательно будет, как он есть у любых более-менее сложных проектов. Он нужен как справочник.
### Механика обработки трафика
@@ -90,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]`. В примере реализована стратегия
```
@@ -110,7 +122,7 @@ nfqws --qnum 200 --debug \
Тип пейлоада - тип данных, содержащихся в пакете или группе пакетов. Например, протокол соединения может быть tls, а пейлоады - tls_client_hello, tls_server_hello, unknown.
Другое важное отличие - отсутствие жестко определенных фаз десинхронизации. То, что вы раньше писали как `fake,multisplit` реализуется двумя
последовательно вызываемыми LUA функциями. Их может быть столько, сколько нужно, учитывая логику прохождения пакетов и операций с ними, и у каждой могут быть свои параметры.
последовательно вызываемыми Lua функциями. Их может быть столько, сколько нужно, учитывая логику прохождения пакетов и операций с ними, и у каждой могут быть свои параметры.
Может даже несколько раз вызываться одна и так же функция с разными параметрами. Так, например, можно послать несколько фейков, причем с разными фулингами.
Конкретный вызов `--lua-desync` функции называется инстансом. Инстанс - это связка имени функции, номера вызова внутри профиля и номера самого профиля.
Это похоже на одну программу, которую можно запустить много раз с разными параметрами.
@@ -118,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`
@@ -155,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 - означает отправить как есть,
@@ -289,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.
```
@@ -350,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
```
@@ -372,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 паттерна.
@@ -405,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,29 +1,62 @@
-- standard automation/orchestration code
-- this is related to making dynamic strategy decisions without rewriting or altering strategy function code
-- orchestrators can decide which instances to call or not to call or pass them dynamic arguments
-- failure 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
function automate_host_record(desync)
local key
if desync.arg.reqhost then
key = desync.track and desync.track.hostname
else
key = host_or_ip(desync)
-- arg: nld=N - cut hostname to N level domain. NLD=2 static.intranet.microsoft.com => microsoft.com
function standard_hostkey(desync)
local hostkey = desync.track and desync.track.hostname
if hostkey then
if desync.arg.nld and tonumber(desync.arg.nld)>0 and not (desync.track and desync.track.hostname_is_ip) then
-- dissect_nld returns nil if domain is invalid or does not have this NLD
-- fall back to original hostkey if it fails
local hktemp = dissect_nld(hostkey, tonumber(desync.arg.nld))
if hktemp then
hostkey = hktemp
end
end
elseif not desync.arg.reqhost then
hostkey = host_ip(desync)
end
if not key then
return hostkey
end
-- per-host storage
-- arg: key - a string - table name inside autostate table. to allow multiple orchestrator instances to use single host storage
-- arg: hostkey - hostkey generator function name
function automate_host_record(desync)
local hostkey, hkf, askey
if desync.arg.hostkey then
if type(_G[desync.arg.hostkey])~="function" then
error("automate: invalid hostkey function '"..desync.arg.hostkey.."'")
end
hkf = _G[desync.arg.hostkey]
else
hkf = standard_hostkey
end
hostkey = hkf(desync)
if not hostkey then
DLOG("automate: host record key unavailable")
return nil
end
DLOG("automate: host record key '"..key.."'")
askey = (desync.arg.key and #desync.arg.key>0) and desync.arg.key or desync.func_instance
DLOG("automate: host record key 'autostate."..askey.."."..hostkey.."'")
if not autostate then
autostate = {}
end
if not autostate[key] then
autostate[key] = {}
if not autostate[askey] then
autostate[askey] = {}
end
return autostate[key]
if not autostate[askey][hostkey] then
autostate[askey][hostkey] = {}
end
return autostate[askey][hostkey]
end
-- per-connection storage
function automate_conn_record(desync)
if not desync.track.lua_state.automate then
desync.track.lua_state.automate = {}
@@ -61,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
@@ -74,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:
@@ -81,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: udp_out - udp: >= outgoing udp packets. default is 3
-- 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 3
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
@@ -139,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.pcounter_orig>=udp_out and desync.track.pcounter_reply<=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.pcounter_orig..">="..udp_out.." udp_in "..desync.track.pcounter_reply.."<="..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
@@ -154,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
@@ -219,37 +359,21 @@ 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
DLOG("circular: current strategy "..hrec.nstrategy)
local dcopy = desync_copy(desync)
while true do
local instance = plan_instance_pop(desync)
if not instance then break end
if instance.arg.strategy and tonumber(instance.arg.strategy)==hrec.nstrategy then
verdict = plan_instance_execute(dcopy, verdict, instance)
verdict = plan_instance_execute(desync, verdict, instance)
end
end
@@ -268,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)
@@ -290,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)
@@ -306,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)
@@ -318,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

@@ -37,7 +37,7 @@ void ConntrackClearHostname(t_ctrack *track)
static void ConntrackClearTrack(t_ctrack *track)
{
ConntrackClearHostname(track);
ReasmClear(&track->reasm_orig);
ReasmClear(&track->reasm_client);
rawpacket_queue_destroy(&track->delayed);
luaL_unref(params.L, LUA_REGISTRYINDEX, track->lua_state);
luaL_unref(params.L, LUA_REGISTRYINDEX, track->lua_instance_cutoff);
@@ -70,24 +70,24 @@ void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_s
p->pool = NULL;
}
void ConntrackExtractConn(t_conn *c, bool bReverse, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr)
void ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis)
{
memset(c, 0, sizeof(*c));
if (ip)
if (dis->ip)
{
c->l3proto = IPPROTO_IP;
c->dst.ip = bReverse ? ip->ip_src : ip->ip_dst;
c->src.ip = bReverse ? ip->ip_dst : ip->ip_src;
c->dst.ip = bReverse ? dis->ip->ip_src : dis->ip->ip_dst;
c->src.ip = bReverse ? dis->ip->ip_dst : dis->ip->ip_src;
}
else if (ip6)
else if (dis->ip6)
{
c->l3proto = IPPROTO_IPV6;
c->dst.ip6 = bReverse ? ip6->ip6_src : ip6->ip6_dst;
c->src.ip6 = bReverse ? ip6->ip6_dst : ip6->ip6_src;
c->dst.ip6 = bReverse ? dis->ip6->ip6_src : dis->ip6->ip6_dst;
c->src.ip6 = bReverse ? dis->ip6->ip6_dst : dis->ip6->ip6_src;
}
else
c->l3proto = -1;
extract_ports(tcphdr, udphdr, &c->l4proto, bReverse ? &c->dport : &c->sport, bReverse ? &c->sport : &c->dport);
extract_ports(dis->tcp, dis->udp, &c->l4proto, bReverse ? &c->dport : &c->sport, bReverse ? &c->sport : &c->dport);
}
@@ -102,8 +102,7 @@ static void ConntrackInitTrack(t_ctrack *t)
{
memset(t, 0, sizeof(*t));
t->l7proto = L7_UNKNOWN;
t->pos.scale_orig = t->pos.scale_reply = SCALE_NONE;
time(&t->pos.t_start);
t->pos.client.scale = t->pos.server.scale = SCALE_NONE;
rawpacket_queue_init(&t->delayed);
lua_newtable(params.L);
t->lua_state = luaL_ref(params.L, LUA_REGISTRYINDEX);
@@ -128,43 +127,79 @@ static t_conntrack_pool *ConntrackNew(t_conntrack_pool **pp, const t_conn *c)
return ctnew;
}
// non-tcp packets are passed with tcphdr=NULL but len_payload filled
static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr *tcphdr, uint32_t len_payload)
static void ConntrackApplyPos(t_ctrack *t, bool bReverse, const struct dissect *dis)
{
uint8_t scale;
uint16_t mss;
t_ctrack_position *direct, *reverse;
direct = bReverse ? &t->pos.server : &t->pos.client;
reverse = bReverse ? &t->pos.client : &t->pos.server;
if (dis->ip6) direct->ip6flow = ntohl(dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_flow);
scale = tcp_find_scale_factor(dis->tcp);
mss = ntohs(tcp_find_mss(dis->tcp));
direct->seq_last = ntohl(dis->tcp->th_seq);
direct->pos = direct->seq_last + dis->len_payload;
reverse->pos = reverse->seq_last = ntohl(dis->tcp->th_ack);
if (t->pos.state == SYN)
direct->uppos_prev = direct->uppos = direct->pos;
else if (dis->len_payload)
{
direct->uppos_prev = direct->uppos;
if (!((direct->pos - direct->uppos) & 0x80000000))
direct->uppos = direct->pos;
}
direct->winsize = ntohs(dis->tcp->th_win);
direct->winsize_calc = direct->winsize;
if (direct->scale != SCALE_NONE) direct->winsize_calc <<= direct->scale;
if (mss && !direct->mss) direct->mss = mss;
if (scale != SCALE_NONE) direct->scale = scale;
if (!direct->rseq_over_2G && ((direct->seq_last - direct->seq0) & 0x80000000))
direct->rseq_over_2G = true;
if (!reverse->rseq_over_2G && ((reverse->seq_last - reverse->seq0) & 0x80000000))
reverse->rseq_over_2G = true;
}
static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct dissect *dis)
{
uint8_t scale;
uint16_t mss;
if (bReverse)
{
t->pos.pcounter_reply++;
t->pos.pdcounter_reply += !!len_payload;
t->pos.pbcounter_reply += len_payload;
t->pos.server.pcounter++;
t->pos.server.pdcounter += !!dis->len_payload;
t->pos.server.pbcounter += dis->len_payload;
}
else
{
t->pos.pcounter_orig++;
t->pos.pdcounter_orig += !!len_payload;
t->pos.pbcounter_orig += len_payload;
t->pos.client.pcounter++;
t->pos.client.pdcounter += !!dis->len_payload;
t->pos.client.pbcounter += dis->len_payload;
}
if (tcphdr)
if (dis->tcp)
{
if (tcp_syn_segment(tcphdr))
if (tcp_syn_segment(dis->tcp))
{
if (t->pos.state != SYN) ConntrackReInitTrack(t); // erase current entry
t->pos.seq0 = ntohl(tcphdr->th_seq);
t->pos.client.seq0 = ntohl(dis->tcp->th_seq);
}
else if (tcp_synack_segment(tcphdr))
else if (tcp_synack_segment(dis->tcp))
{
// ignore SA dups
uint32_t seq0 = ntohl(tcphdr->th_ack) - 1;
if (t->pos.state != SYN && t->pos.seq0 != seq0)
uint32_t seq0 = ntohl(dis->tcp->th_ack) - 1;
if (t->pos.state != SYN && t->pos.client.seq0 != seq0)
ConntrackReInitTrack(t); // erase current entry
if (!t->pos.seq0) t->pos.seq0 = seq0;
t->pos.ack0 = ntohl(tcphdr->th_seq);
if (!t->pos.client.seq0) t->pos.client.seq0 = seq0;
t->pos.server.seq0 = ntohl(dis->tcp->th_seq);
}
else if (tcphdr->th_flags & (TH_FIN | TH_RST))
else if (dis->tcp->th_flags & (TH_FIN | TH_RST))
{
t->pos.state = FIN;
}
@@ -173,73 +208,24 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
if (t->pos.state == SYN)
{
t->pos.state = ESTABLISHED;
if (!bReverse && !t->pos.ack0) t->pos.ack0 = ntohl(tcphdr->th_ack) - 1;
if (!bReverse && !t->pos.server.seq0) t->pos.server.seq0 = ntohl(dis->tcp->th_ack) - 1;
}
}
scale = tcp_find_scale_factor(tcphdr);
mss = ntohs(tcp_find_mss(tcphdr));
if (bReverse)
{
t->pos.ack_last = ntohl(tcphdr->th_seq);
t->pos.pos_orig = t->pos.seq_last = ntohl(tcphdr->th_ack);
t->pos.pos_reply = t->pos.ack_last + len_payload;
if (t->pos.state == SYN)
t->pos.uppos_reply_prev = t->pos.uppos_reply = t->pos.pos_reply;
else if (len_payload)
{
t->pos.uppos_reply_prev = t->pos.uppos_reply;
if (!((t->pos.pos_reply - t->pos.uppos_reply) & 0x80000000))
t->pos.uppos_reply = t->pos.pos_reply;
}
t->pos.winsize_reply = ntohs(tcphdr->th_win);
t->pos.winsize_reply_calc = t->pos.winsize_reply;
if (t->pos.scale_reply != SCALE_NONE) t->pos.winsize_reply_calc <<= t->pos.scale_reply;
if (mss && !t->pos.mss_reply) t->pos.mss_reply = mss;
if (scale != SCALE_NONE) t->pos.scale_reply = scale;
}
else
{
t->pos.seq_last = ntohl(tcphdr->th_seq);
t->pos.pos_orig = t->pos.seq_last + len_payload;
t->pos.pos_reply = t->pos.ack_last = ntohl(tcphdr->th_ack);
if (t->pos.state == SYN)
t->pos.uppos_orig_prev = t->pos.uppos_orig = t->pos.pos_orig;
else if (len_payload)
{
t->pos.uppos_orig_prev = t->pos.uppos_orig;
if (!((t->pos.pos_orig - t->pos.uppos_orig) & 0x80000000))
t->pos.uppos_orig = t->pos.pos_orig;
}
t->pos.winsize_orig = ntohs(tcphdr->th_win);
t->pos.winsize_orig_calc = t->pos.winsize_orig;
if (t->pos.scale_orig != SCALE_NONE) t->pos.winsize_orig_calc <<= t->pos.scale_orig;
if (mss && !t->pos.mss_reply) t->pos.mss_orig = mss;
if (scale != SCALE_NONE) t->pos.scale_orig = scale;
}
}
else
{
if (bReverse)
{
t->pos.ack_last = t->pos.pos_reply;
t->pos.pos_reply += len_payload;
}
else
{
t->pos.seq_last = t->pos.pos_orig;
t->pos.pos_orig += len_payload;
}
ConntrackApplyPos(t, bReverse, dis);
}
time(&t->pos.t_last);
clock_gettime(CLOCK_REALTIME, &t->pos.t_last);
// make sure t_start gets exactly the same value as first t_last
if (!t->t_start.tv_sec) t->t_start = t->pos.t_last;
}
static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse)
static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse)
{
t_conn conn, connswp;
t_conntrack_pool *ctr;
ConntrackExtractConn(&conn, false, ip, ip6, tcphdr, udphdr);
ConntrackExtractConn(&conn, false, dis);
if ((ctr = ConntrackPoolSearch(*pp, &conn)))
{
if (bReverse) *bReverse = false;
@@ -258,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
@@ -281,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;
}
}
@@ -301,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);
@@ -320,20 +306,22 @@ static bool ConntrackPoolDropPool(t_conntrack_pool **pp, const struct ip *ip, co
HASH_DEL(*pp, t); ConntrackFreeElem(t);
return true;
}
bool ConntrackPoolDrop(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr)
bool ConntrackPoolDrop(t_conntrack *p, const struct dissect *dis)
{
return ConntrackPoolDropPool(&p->pool, ip, ip6, tcphdr, udphdr);
return ConntrackPoolDropPool(&p->pool, dis);
}
void ConntrackPoolPurge(t_conntrack *p)
{
time_t tidle, tnow = time(NULL);
time_t tidle;
struct timespec tnow;
t_conntrack_pool *t, *tmp;
if ((tnow - p->t_last_purge) >= p->t_purge_interval)
if (clock_gettime(CLOCK_REALTIME, &tnow)) return;
if ((tnow.tv_sec - p->t_last_purge) >= p->t_purge_interval)
{
HASH_ITER(hh, p->pool, t, tmp) {
tidle = tnow - t->track.pos.t_last;
tidle = tnow.tv_sec - t->track.pos.t_last.tv_sec;
if (t->track.b_cutoff ||
(t->conn.l4proto == IPPROTO_TCP && (
(t->track.pos.state == SYN && tidle >= p->timeout_syn) ||
@@ -345,7 +333,7 @@ void ConntrackPoolPurge(t_conntrack *p)
HASH_DEL(p->pool, t); ConntrackFreeElem(t);
}
}
p->t_last_purge = tnow;
p->t_last_purge = tnow.tv_sec;
}
}
@@ -357,29 +345,31 @@ static void taddr2str(uint8_t l3proto, const t_addr *a, char *buf, size_t bufsiz
void ConntrackPoolDump(const t_conntrack *p)
{
t_conntrack_pool *t, *tmp;
struct timespec tnow;
char sa1[40], sa2[40];
time_t tnow = time(NULL);
if (clock_gettime(CLOCK_REALTIME, &tnow)) return;
HASH_ITER(hh, p->pool, t, tmp) {
taddr2str(t->conn.l3proto, &t->conn.src, sa1, sizeof(sa1));
taddr2str(t->conn.l3proto, &t->conn.dst, sa2, sizeof(sa2));
printf("%s [%s]:%u => [%s]:%u : %s : t0=%llu last=t0+%llu now=last+%llu orig=d%llu/n%llu/b%llu reply=d%llu/n%llu/b%lld ",
printf("%s [%s]:%u => [%s]:%u : %s : t0=%llu last=t0+%llu now=last+%llu client=d%llu/n%llu/b%llu server=d%llu/n%llu/b%lld ",
proto_name(t->conn.l4proto),
sa1, t->conn.sport, sa2, t->conn.dport,
t->conn.l4proto == IPPROTO_TCP ? connstate_s[t->track.pos.state] : "-",
(unsigned long long)t->track.pos.t_start, (unsigned long long)(t->track.pos.t_last - t->track.pos.t_start), (unsigned long long)(tnow - t->track.pos.t_last),
(unsigned long long)t->track.pos.pdcounter_orig, (unsigned long long)t->track.pos.pcounter_orig, (unsigned long long)t->track.pos.pbcounter_orig,
(unsigned long long)t->track.pos.pdcounter_reply, (unsigned long long)t->track.pos.pcounter_reply, (unsigned long long)t->track.pos.pbcounter_reply);
(unsigned long long)t->track.t_start.tv_sec, (unsigned long long)(t->track.pos.t_last.tv_sec - t->track.t_start.tv_sec), (unsigned long long)(tnow.tv_sec - t->track.pos.t_last.tv_sec),
(unsigned long long)t->track.pos.client.pdcounter, (unsigned long long)t->track.pos.client.pcounter, (unsigned long long)t->track.pos.client.pbcounter,
(unsigned long long)t->track.pos.server.pdcounter, (unsigned long long)t->track.pos.server.pcounter, (unsigned long long)t->track.pos.server.pbcounter);
if (t->conn.l4proto == IPPROTO_TCP)
printf("seq0=%u rseq=%u pos_orig=%u ack0=%u rack=%u pos_reply=%u mss_orig=%u mss_reply=%u wsize_orig=%u:%d wsize_reply=%u:%d",
t->track.pos.seq0, t->track.pos.seq_last - t->track.pos.seq0, t->track.pos.pos_orig - t->track.pos.seq0,
t->track.pos.ack0, t->track.pos.ack_last - t->track.pos.ack0, t->track.pos.pos_reply - t->track.pos.ack0,
t->track.pos.mss_orig, t->track.pos.mss_reply,
t->track.pos.winsize_orig, t->track.pos.scale_orig == SCALE_NONE ? -1 : t->track.pos.scale_orig,
t->track.pos.winsize_reply, t->track.pos.scale_reply == SCALE_NONE ? -1 : t->track.pos.scale_reply);
printf("seq0=%u rseq=%u client.pos=%u ack0=%u rack=%u server.pos=%u client.mss=%u server.mss=%u client.wsize=%u:%d server.wsize=%u:%d",
t->track.pos.client.seq0, t->track.pos.client.seq_last - t->track.pos.client.seq0, t->track.pos.client.pos - t->track.pos.client.seq0,
t->track.pos.server.seq0, t->track.pos.server.seq_last - t->track.pos.server.seq0, t->track.pos.server.pos - t->track.pos.server.seq0,
t->track.pos.client.mss, t->track.pos.server.mss,
t->track.pos.client.winsize, t->track.pos.client.scale == SCALE_NONE ? -1 : t->track.pos.client.scale,
t->track.pos.server.winsize, t->track.pos.server.scale == SCALE_NONE ? -1 : t->track.pos.server.scale);
else
printf("rseq=%u pos_orig=%u rack=%u pos_reply=%u",
t->track.pos.seq_last, t->track.pos.pos_orig,
t->track.pos.ack_last, t->track.pos.pos_reply);
printf("rseq=%u client.pos=%u rack=%u server.pos=%u",
t->track.pos.client.seq_last, t->track.pos.client.pos,
t->track.pos.server.seq_last, t->track.pos.server.pos);
printf(" req_retrans=%u cutoff=%u lua_in_cutoff=%u lua_out_cutoff=%u hostname=%s l7proto=%s\n",
t->track.req_retrans_counter, t->track.b_cutoff, t->track.b_lua_in_cutoff, t->track.b_lua_out_cutoff, t->track.hostname, l7proto_str(t->track.l7proto));
};

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
@@ -54,14 +55,16 @@ typedef struct
bool bCheckDone, bCheckResult, bCheckExcluded; // hostlist check result cache
uint8_t ipproto;
struct timespec t_start;
// this block of data can change between delayed (queued) packets. need to remeber this data for each packet for further replay
t_ctrack_position pos;
t_ctrack_positions pos;
struct desync_profile *dp; // desync profile cache
bool dp_search_complete;
uint8_t req_retrans_counter; // number of request retransmissions
bool retrans_detect_finalized;
bool failure_detect_finalized;
uint8_t incoming_ttl;
@@ -78,7 +81,7 @@ typedef struct
int lua_state; // registry index of associated LUA object
int lua_instance_cutoff; // registry index of per connection function instance cutoff table
t_reassemble reasm_orig;
t_reassemble reasm_client;
struct rawpacket_tailhead delayed;
} t_ctrack;
@@ -98,11 +101,11 @@ typedef struct
void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_syn, uint32_t timeout_established, uint32_t timeout_fin, uint32_t timeout_udp);
void ConntrackPoolDestroy(t_conntrack *p);
bool ConntrackPoolFeed(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse);
bool ConntrackPoolFeed(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse);
// do not create, do not update. only find existing
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse);
bool ConntrackPoolDrop(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr);
void CaonntrackExtractConn(t_conn *c, bool bReverse, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr);
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse);
bool ConntrackPoolDrop(t_conntrack *p, const struct dissect *dis);
void ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis);
void ConntrackPoolDump(const t_conntrack *p);
void ConntrackPoolPurge(t_conntrack *p);
void ConntrackClearHostname(t_ctrack *track);

View File

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

View File

@@ -40,9 +40,6 @@
#include <linux/genetlink.h>
#include <libmnl/libmnl.h>
#include <net/if.h>
#define _LINUX_IF_H // prevent conflict between linux/if.h and net/if.h in old gcc 4.x
#include <linux/wireless.h>
#include <sys/ioctl.h>
#endif
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment)
@@ -550,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)
{
@@ -721,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;
@@ -737,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;
}
@@ -1256,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;
@@ -1578,9 +1633,9 @@ bool rawsend_queue(struct rawpacket_tailhead *q)
// linux-specific wlan retrieval implementation
typedef void netlink_prepare_nlh_cb_t(struct nlmsghdr *nlh);
typedef void netlink_prepare_nlh_cb_t(struct nlmsghdr *nlh, void *param);
static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, uint16_t flags, uint8_t cmd, uint8_t version, netlink_prepare_nlh_cb_t cb_prepare_nlh, mnl_cb_t cb_data, void *data)
static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, uint16_t flags, uint8_t cmd, uint8_t version, netlink_prepare_nlh_cb_t cb_prepare_nlh, void *prepare_data, mnl_cb_t cb_data, void *data)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
@@ -1595,7 +1650,7 @@ static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, u
genl->cmd = cmd;
genl->version = version;
if (cb_prepare_nlh) cb_prepare_nlh(nlh);
if (cb_prepare_nlh) cb_prepare_nlh(nlh, prepare_data);
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
{
@@ -1619,7 +1674,7 @@ static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, u
return false;
}
static void wlan_id_prepare(struct nlmsghdr *nlh)
static void wlan_id_prepare(struct nlmsghdr *nlh, void *param)
{
mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, "nl80211");
}
@@ -1651,7 +1706,7 @@ static int wlan_id_cb(const struct nlmsghdr *nlh, void *data)
static uint16_t wlan_get_family_id(struct mnl_socket* nl)
{
uint16_t id;
return netlink_genl_simple_transact(nl, GENL_ID_CTRL, NLM_F_REQUEST | NLM_F_ACK, CTRL_CMD_GETFAMILY, 1, wlan_id_prepare, wlan_id_cb, &id) ? id : 0;
return netlink_genl_simple_transact(nl, GENL_ID_CTRL, NLM_F_REQUEST | NLM_F_ACK, CTRL_CMD_GETFAMILY, 1, wlan_id_prepare, NULL, wlan_id_cb, &id) ? id : 0;
}
static int wlan_info_attr_cb(const struct nlattr *attr, void *data)
@@ -1686,42 +1741,130 @@ static int wlan_info_attr_cb(const struct nlattr *attr, void *data)
}
return MNL_CB_OK;
}
struct wlan_info_req
{
struct wlan_interface_collection *wc;
bool bReqSSID;
};
static int wlan_info_cb(const struct nlmsghdr *nlh, void *data)
{
int ret;
struct wlan_info_req *wr = (struct wlan_info_req*)data;
if (wr->wc->count>=WLAN_INTERFACE_MAX) return MNL_CB_OK;
memset(wr->wc->wlan + wr->wc->count,0,sizeof(struct wlan_interface));
ret = mnl_attr_parse(nlh, sizeof(struct genlmsghdr), wlan_info_attr_cb, wr->wc->wlan + wr->wc->count);
if (ret>=0 && (!wr->bReqSSID || *wr->wc->wlan[wr->wc->count].ssid) && *wr->wc->wlan[wr->wc->count].ifname && wr->wc->wlan[wr->wc->count].ifindex)
wr->wc->count++;
return ret;
}
static bool wlan_info(struct mnl_socket* nl, uint16_t wlan_family_id, struct wlan_interface_collection* w, bool bReqSSID)
{
struct wlan_info_req req = { .bReqSSID = bReqSSID, .wc = w };
return netlink_genl_simple_transact(nl, wlan_family_id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP, NL80211_CMD_GET_INTERFACE, 0, NULL, NULL, wlan_info_cb, &req);
}
static void scan_prepare(struct nlmsghdr *nlh, void *param)
{
mnl_attr_put_u32(nlh, NL80211_ATTR_IFINDEX, *(int*)param);
}
static uint8_t *find_ie(uint8_t *buf, size_t len, uint8_t ie)
{
while (len>=2)
{
if (len<(2+buf[1])) break;
if (buf[0]==ie) return buf;
buf+=buf[1]+2;
len-=buf[1]+2;
}
return NULL;
}
static int scan_info_attr_cb(const struct nlattr *attr, void *data)
{
struct wlan_interface *wlan = (struct wlan_interface *)data;
const struct nlattr *nested;
uint8_t *payload, *ie;
uint16_t payload_len;
bool ok;
switch(mnl_attr_get_type(attr))
{
case NL80211_ATTR_IFINDEX:
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
{
DLOG_PERROR("mnl_attr_validate");
return MNL_CB_ERROR;
}
wlan->ifindex = mnl_attr_get_u32(attr);
if (!if_indextoname(wlan->ifindex, wlan->ifname))
DLOG_PERROR("if_indextoname");
break;
case NL80211_ATTR_BSS:
if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
{
DLOG_PERROR("mnl_attr_validate");
return MNL_CB_ERROR;
}
ok = false;
mnl_attr_for_each_nested(nested, attr)
{
if (mnl_attr_get_type(nested)==NL80211_BSS_STATUS)
{
uint32_t status = mnl_attr_get_u32(nested);
if (status==NL80211_BSS_STATUS_ASSOCIATED || status==NL80211_BSS_STATUS_AUTHENTICATED || status==NL80211_BSS_STATUS_IBSS_JOINED)
{
ok=1;
break;
}
}
}
if (!ok) break;
mnl_attr_for_each_nested(nested, attr)
{
switch(mnl_attr_get_type(nested))
{
case NL80211_BSS_INFORMATION_ELEMENTS:
payload_len = mnl_attr_get_payload_len(nested);
payload = mnl_attr_get_payload(nested);
ie = find_ie(payload,payload_len,0);
if (ie)
{
uint8_t l = ie[1];
if (l>=(sizeof(wlan->ssid))) l=sizeof(wlan->ssid)-1;
memcpy(wlan->ssid,ie+2,l);
wlan->ssid[l]=0;
}
break;
}
}
break;
}
return MNL_CB_OK;
}
static int scan_info_cb(const struct nlmsghdr *nlh, void *data)
{
int ret;
struct wlan_interface_collection *wc = (struct wlan_interface_collection*)data;
if (wc->count>=WLAN_INTERFACE_MAX) return MNL_CB_OK;
memset(wc->wlan+wc->count,0,sizeof(wc->wlan[0]));
ret = mnl_attr_parse(nlh, sizeof(struct genlmsghdr), wlan_info_attr_cb, wc->wlan+wc->count);
if (ret>=0 && *wc->wlan[wc->count].ifname && wc->wlan[wc->count].ifindex)
{
if (*wc->wlan[wc->count].ssid)
wc->count++;
else
{
// sometimes nl80211 does not return SSID but wireless ext does
int wext_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (wext_fd!=-1)
{
struct iwreq req;
snprintf(req.ifr_ifrn.ifrn_name,sizeof(req.ifr_ifrn.ifrn_name),"%s",wc->wlan[wc->count].ifname);
req.u.essid.pointer = wc->wlan[wc->count].ssid;
req.u.essid.length = sizeof(wc->wlan[wc->count].ssid);
req.u.essid.flags = 0;
if (ioctl(wext_fd, SIOCGIWESSID, &req)!=-1)
if (*wc->wlan[wc->count].ssid)
wc->count++;
close(wext_fd);
}
}
}
ret = mnl_attr_parse(nlh, sizeof(struct genlmsghdr), scan_info_attr_cb, wc->wlan+wc->count);
if (ret>=0 && *wc->wlan[wc->count].ssid && *wc->wlan[wc->count].ifname && wc->wlan[wc->count].ifindex)
wc->count++;
return ret;
}
static bool wlan_info(struct mnl_socket* nl, uint16_t wlan_family_id, struct wlan_interface_collection* w)
static bool scan_info(struct mnl_socket* nl, uint16_t wlan_family_id, struct wlan_interface_collection* w)
{
return netlink_genl_simple_transact(nl, wlan_family_id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP, NL80211_CMD_GET_INTERFACE, 0, NULL, wlan_info_cb, w);
struct wlan_interface_collection wc_all = { .count = 0 };
// wlan_info does not return ssid since kernel 5.19
// it's used to enumerate all wifi interfaces then call scan_info on each
if (!wlan_info(nl, wlan_family_id, &wc_all, false)) return false;
for(int i=0;i<wc_all.count;i++)
if (!netlink_genl_simple_transact(nl, wlan_family_id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0, scan_prepare, (void*)&wc_all.wlan[i].ifindex, scan_info_cb, w))
return false;
return true;
}
static bool wlan_init80211(struct mnl_socket** nl)
{
if (!(*nl = mnl_socket_open(NETLINK_GENERIC)))
@@ -1755,7 +1898,7 @@ static bool wlan_info_rate_limited(struct mnl_socket* nl, uint16_t wlan_family_i
// do not purge too often to save resources
if (wlan_info_last != now)
{
bres = wlan_info(nl,wlan_family_id,w);
bres = scan_info(nl,wlan_family_id,w);
wlan_info_last = now;
}
return bres;
@@ -1781,10 +1924,6 @@ bool wlan_info_init(void)
}
return true;
}
bool wlan_info_get(void)
{
return wlan_info(nl_wifi, id_nl80211, &wlans);
}
bool wlan_info_get_rate_limited(void)
{
return wlan_info_rate_limited(nl_wifi, id_nl80211, &wlans);

View File

@@ -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);
@@ -190,7 +192,6 @@ extern struct wlan_interface_collection wlans;
void wlan_info_deinit(void);
bool wlan_info_init(void);
bool wlan_info_get(void);
bool wlan_info_get_rate_limited(void);
const char *wlan_ssid_search_ifname(const char *ifname);
const char *wlan_ssid_search_ifidx(int ifidx);

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -7,7 +7,7 @@
#define BUFMIN 128
#define BUFCHUNK (1024*128)
int z_readfile(FILE *F, char **buf, size_t *size)
int z_readfile(FILE *F, char **buf, size_t *size, size_t extra_alloc)
{
z_stream zs;
int r;
@@ -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)
@@ -514,7 +541,7 @@ bool pf_is_empty(const port_filter *pf)
bool packet_pos_parse(const char *s, struct packet_pos *pos)
{
if (*s!='n' && *s!='d' && *s!='s' && *s!='b' && *s!='x' && *s!='a') return false;
if (*s!='n' && *s!='d' && *s!='s' && *s!='p' && *s!='b' && *s!='x' && *s!='a') return false;
pos->mode=*s;
if (pos->mode=='x' || pos->mode=='a')
{

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);
@@ -841,7 +922,7 @@ static int luacall_execution_plan(lua_State *L)
range = ctx->incoming ? &func->range_in : &func->range_out;
lua_pushinteger(params.L, n - ctx->func_n);
lua_createtable(params.L, 0, 6);
lua_pushf_args(&func->args, -1);
lua_pushf_args(&func->args, -1, false);
lua_pushf_str("func", func->func);
lua_pushf_int("func_n", ctx->func_n);
lua_pushf_str("func_instance", instance);
@@ -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);
@@ -929,6 +1002,18 @@ void lua_pushi_lint(lua_Integer idx, int64_t v)
lua_pushlint(params.L, v);
lua_rawset(params.L,-3);
}
void lua_pushf_number(const char *field, lua_Number v)
{
lua_pushstring(params.L, field);
lua_pushnumber(params.L, v);
lua_rawset(params.L,-3);
}
void lua_pushi_number(lua_Integer idx, lua_Number v)
{
lua_pushinteger(params.L, idx);
lua_pushnumber(params.L, v);
lua_rawset(params.L,-3);
}
void lua_pushf_bool(const char *field, bool b)
{
lua_pushstring(params.L, field);
@@ -1239,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
@@ -1260,23 +1347,46 @@ void lua_pushf_dissect(const struct dissect *dis)
lua_rawset(params.L,-3);
}
void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_position *pos)
void lua_pushf_ctrack_pos(const t_ctrack *ctrack, const t_ctrack_position *pos)
{
LUA_STACK_GUARD_ENTER(params.L)
if (!pos) pos = &ctrack->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, 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);
lua_pushf_int("winsize", pos->winsize);
lua_pushf_int("winsize_calc", pos->winsize_calc);
lua_pushf_int("scale", pos->scale);
lua_pushf_int("mss", pos->mss);
lua_rawset(params.L,-3);
}
LUA_STACK_GUARD_LEAVE(params.L, 0)
}
void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_positions *tpos, bool bIncoming)
{
LUA_STACK_GUARD_ENTER(params.L)
if (!tpos) tpos = &ctrack->pos;
lua_pushliteral(params.L, "track");
if (ctrack)
{
lua_createtable(params.L, 0, 13 + (ctrack->ipproto == IPPROTO_TCP));
lua_createtable(params.L, 0, 9);
lua_pushf_lint("pcounter_orig", pos->pcounter_orig);
lua_pushf_lint("pdcounter_orig", pos->pdcounter_orig);
lua_pushf_lint("pbcounter_orig", pos->pbcounter_orig);
lua_pushf_lint("pcounter_reply", pos->pcounter_reply);
lua_pushf_lint("pdcounter_reply", pos->pdcounter_reply);
lua_pushf_lint("pbcounter_reply", pos->pbcounter_reply);
if (ctrack->incoming_ttl)
lua_pushf_int("incoming_ttl", ctrack->incoming_ttl);
else
@@ -1287,31 +1397,38 @@ void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_position *pos)
lua_pushf_reg("lua_state", ctrack->lua_state);
lua_pushf_bool("lua_in_cutoff", ctrack->b_lua_in_cutoff);
lua_pushf_bool("lua_out_cutoff", ctrack->b_lua_out_cutoff);
lua_pushf_lint("t_start", (lua_Number)ctrack->t_start.tv_sec + ctrack->t_start.tv_nsec/1000000000.);
if (ctrack->ipproto == IPPROTO_TCP)
{
lua_pushliteral(params.L, "tcp");
lua_createtable(params.L, 0, 18);
lua_pushf_lint("seq0", pos->seq0);
lua_pushf_lint("seq", pos->seq_last);
lua_pushf_lint("ack0", pos->ack0);
lua_pushf_lint("ack", pos->ack_last);
lua_pushf_int("pos_orig", pos->pos_orig - pos->seq0);
lua_pushf_int("uppos_orig", pos->uppos_orig - pos->seq0);
lua_pushf_int("uppos_orig_prev", pos->uppos_orig_prev - pos->seq0);
lua_pushf_int("winsize_orig", pos->winsize_orig);
lua_pushf_int("winsize_orig_calc", pos->winsize_orig_calc);
lua_pushf_int("scale_orig", pos->scale_orig);
lua_pushf_int("mss_orig", pos->mss_orig);
lua_pushf_int("pos_reply", pos->pos_reply - pos->ack0);
lua_pushf_int("uppos_reply", pos->uppos_reply - pos->ack0);
lua_pushf_int("uppos_reply_prev", pos->uppos_reply_prev - pos->ack0);
lua_pushf_int("winsize_reply", pos->winsize_reply);
lua_pushf_int("winsize_reply_calc", pos->winsize_reply_calc);
lua_pushf_int("scale_reply", pos->scale_reply);
lua_pushf_int("mss_reply", pos->mss_reply);
lua_rawset(params.L,-3);
}
lua_pushliteral(params.L, "pos");
lua_createtable(params.L, 0, 5);
// orig, reply related to connection logical direction
// for tcp orig is client (who connects), reply is server (who listens).
// for orig is the first seen party, reply is another party
lua_pushf_number("dt",
(lua_Number)tpos->t_last.tv_sec - (lua_Number)ctrack->t_start.tv_sec +
(tpos->t_last.tv_nsec - ctrack->t_start.tv_nsec)/1000000000.);
lua_pushliteral(params.L, "client");
lua_newtable(params.L);
lua_pushf_ctrack_pos(ctrack, &tpos->client);
lua_rawset(params.L,-3);
lua_pushliteral(params.L, "server");
lua_newtable(params.L);
lua_pushf_ctrack_pos(ctrack, &tpos->server);
lua_rawset(params.L,-3);
// direct and reverse are adjusted for server mode. in server mode orig and reply are exchanged.
lua_pushliteral(params.L, "direct");
lua_getfield(params.L, -2, (params.server ^ bIncoming) ? "server" : "client");
lua_rawset(params.L,-3);
lua_pushliteral(params.L, "reverse");
lua_getfield(params.L, -2, (params.server ^ bIncoming) ? "client" : "server");
lua_rawset(params.L,-3);
lua_rawset(params.L,-3);
}
else
lua_pushnil(params.L);
@@ -1320,7 +1437,7 @@ void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_position *pos)
LUA_STACK_GUARD_LEAVE(params.L, 0)
}
void lua_pushf_args(const struct str2_list_head *args, int idx_desync)
void lua_pushf_args(const struct str2_list_head *args, int idx_desync, bool subst_prefix)
{
// var=val - pass val string
// var=%val - subst 'val' blob
@@ -1341,17 +1458,22 @@ void lua_pushf_args(const struct str2_list_head *args, int idx_desync)
{
var = arg->str1;
val = arg->str2 ? arg->str2 : "";
if (val[0]=='\\' && (val[1]=='%' || val[1]=='#'))
// escape char
lua_pushf_str(var, val+1);
else if (val[0]=='%')
lua_pushf_blob(idx_desync, var, val+1);
else if (val[0]=='#')
if (subst_prefix)
{
lua_push_blob(idx_desync, val+1);
lua_Integer len = lua_rawlen(params.L, -1);
lua_pop(params.L,1);
lua_pushf_int(var, len);
if (val[0]=='\\' && (val[1]=='%' || val[1]=='#'))
// escape char
lua_pushf_str(var, val+1);
else if (val[0]=='%')
lua_pushf_blob(idx_desync, var, val+1);
else if (val[0]=='#')
{
lua_push_blob(idx_desync, val+1);
lua_Integer len = lua_rawlen(params.L, -1);
lua_pop(params.L,1);
lua_pushf_int(var, len);
}
else
lua_pushf_str(var, val);
}
else
lua_pushf_str(var, val);
@@ -1615,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);
@@ -1947,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);
@@ -2090,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)
@@ -2131,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)
@@ -2778,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;
@@ -2810,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;
@@ -2955,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},
@@ -3034,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
@@ -3045,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

@@ -34,6 +34,7 @@
#endif
// pushing and not popping inside luacall cause memory leak
// these macros ensure correct stack position or throw error if not
#define LUA_STACK_GUARD_ENTER(L) int _lsg=lua_gettop(L);
#define LUA_STACK_GUARD_LEAVE(L,N) if ((_lsg+N)!=lua_gettop(L)) luaL_error(L,"stack guard failure");
#define LUA_STACK_GUARD_RETURN(L,N) LUA_STACK_GUARD_LEAVE(L,N); return N;
@@ -68,6 +69,8 @@ void lua_pushf_int(const char *field, lua_Integer v);
void lua_pushi_int(lua_Integer idx, lua_Integer v);
void lua_pushf_lint(const char *field, int64_t v);
void lua_pushi_lint(lua_Integer idx, int64_t v);
void lua_pushf_number(const char *field, lua_Number v);
void lua_pushi_number(lua_Integer idx, lua_Number v);
void lua_push_raw(const void *v, size_t l);
void lua_pushf_raw(const char *field, const void *v, size_t l);
void lua_pushi_raw(lua_Integer idx, const void *v, size_t l);
@@ -86,8 +89,8 @@ void lua_pushf_iphdr(const struct ip *ip, size_t len);
void lua_pushf_ip6hdr(const struct ip6_hdr *ip6, size_t len);
void lua_push_dissect(const struct dissect *dis);
void lua_pushf_dissect(const struct dissect *dis);
void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_position *pos);
void lua_pushf_args(const struct str2_list_head *args, int idx_desync);
void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_positions *tpos, bool bIncoming);
void lua_pushf_args(const struct str2_list_head *args, int idx_desync, bool subst_prefix);
void lua_pushf_pos(const char *name, const struct packet_pos *pos);
void lua_pushf_range(const char *name, const struct packet_range *range);
void lua_pushf_global(const char *field, const char *global);
@@ -98,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,11 +1436,15 @@ 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"
" --hostlist-auto-debug=<logfile>\t\t\t; debug auto hostlist positives (global parameter)\n"
"\nLUA PACKET PASS MODE:\n"
" --payload=type[,type]\t\t\t\t\t; set payload types following LUA functions should process : %s\n"
" --out-range=[(n|a|d|s)<int>](-|<)[(n|a|d|s)<int>]\t; set outgoing packet range for following LUA functions. '-' - include end pos, '<' - not include. prefix meaning : n - packet number, d - data packet number, s - relative sequence, b - byte count, x - never, a - always\n"
" --in-range=[(n|a|d|s)<int>](-|<)[(n|a|d|s)<int>]\t; set incoming packet range for following LUA functions. '-' - include end pos, '<' - not include. prefix meaning : n - packet number, d - data packet number, s - relative sequence, b - byte count, x - never, a - always\n"
" --out-range=[(n|a|d|s|p)<int>](-|<)[(n|a|d|s|p)<int>]\t; set outgoing packet range for following LUA functions. '-' - include end pos, '<' - not include. prefix meaning : n - packet number, d - data packet number, s - relative sequence, p - data position relative sequence, b - byte count, x - never, a - always\n"
" --in-range=[(n|a|d|s|p)<int>](-|<)[(n|a|d|s|p)<int>]\t; set incoming packet range for following LUA functions. '-' - include end pos, '<' - not include. prefix meaning : n - packet number, d - data packet number, s - relative sequence, p - data position relative sequence, b - byte count, x - never, a - always\n"
"\nLUA DESYNC ACTION:\n"
" --lua-desync=<functon>[:param1=val1[:param2=val2]]\t; call LUA function when packet received\n",
#if defined(__linux__) || defined(SO_USER_COOKIE)
@@ -1450,7 +1455,9 @@ static void exithelp(void)
LUA_GC_INTERVAL,
all_protos,
HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT,
HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT, HOSTLIST_AUTO_RETRANS_MAXSEQ,
HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT,
HOSTLIST_AUTO_RETRANS_MAXSEQ, HOSTLIST_AUTO_INCOMING_MAXSEQ,
HOSTLIST_AUTO_UDP_OUT, HOSTLIST_AUTO_UDP_IN,
all_payloads
);
exit(1);
@@ -1548,6 +1555,10 @@ 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,
IDX_HOSTLIST_AUTO_DEBUG,
IDX_NEW,
IDX_SKIP,
@@ -1633,6 +1644,10 @@ 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},
[IDX_HOSTLIST_AUTO_DEBUG] = {"hostlist-auto-debug", required_argument, 0, 0},
[IDX_NEW] = {"new", no_argument, 0, 0},
[IDX_SKIP] = {"skip", no_argument, 0, 0},
@@ -1695,22 +1710,6 @@ static const struct option long_options[] = {
int main(int argc, char **argv)
{
/*
t_reassemble t;
ReasmInit(&t,16,-10);
memset(t.packet,0,16);
bool b;
b=ReasmFeed(&t,-10,"0123456789",10);
printf("b=%u size=%zu seq=%d s=%s\n",b,t.size_present,t.seq,t.packet);
b=ReasmFeed(&t,0,"YOREK",5);
printf("b=%u size=%zu seq=%d s=%s\n",b,t.size_present,t.seq,t.packet);
b=ReasmFeed(&t,-12,"XOR",3);
printf("b=%u size=%zu seq=%d s=%s\n",b,t.size_present,t.seq,t.packet);
b=ReasmFeed(&t,3,"abc",3);
printf("b=%u size=%zu seq=%d s=%s\n",b,t.size_present,t.seq,t.packet);
return 0;
*/
#ifdef __CYGWIN__
if (service_run(argc, argv))
{
@@ -1817,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;
}
@@ -2100,6 +2100,18 @@ int main(int argc, char **argv)
case IDX_HOSTLIST_AUTO_RETRANS_MAXSEQ:
dp->hostlist_auto_retrans_maxseq = (uint32_t)atoi(optarg);
break;
case IDX_HOSTLIST_AUTO_INCOMING_MAXSEQ:
dp->hostlist_auto_incoming_maxseq = (uint32_t)atoi(optarg);
break;
case IDX_HOSTLIST_AUTO_RETRANS_RESET:
dp->hostlist_auto_retrans_reset = !optarg || !!atoi(optarg);
break;
case IDX_HOSTLIST_AUTO_UDP_OUT:
dp->hostlist_auto_udp_out = atoi(optarg);
break;
case IDX_HOSTLIST_AUTO_UDP_IN:
dp->hostlist_auto_udp_in = atoi(optarg);
break;
case IDX_HOSTLIST_AUTO_DEBUG:
{
FILE *F = fopen(optarg, "a+t");

View File

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

View File

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

View File

@@ -16,8 +16,8 @@ struct rawpacket
uint32_t fwmark;
size_t len, len_payload;
uint8_t *packet;
t_ctrack_position pos;
bool pos_present;
t_ctrack_positions tpos;
bool tpos_present;
TAILQ_ENTRY(rawpacket) next;
};
TAILQ_HEAD(rawpacket_tailhead, rawpacket);
@@ -26,6 +26,6 @@ void rawpacket_queue_init(struct rawpacket_tailhead *q);
void rawpacket_queue_destroy(struct rawpacket_tailhead *q);
bool rawpacket_queue_empty(const struct rawpacket_tailhead *q);
unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q);
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_position *pos);
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_positions *tpos);
struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q);
void rawpacket_free(struct rawpacket *rp);

View File

@@ -112,7 +112,7 @@ int DLOG_FILENAME_VA(const char *filename, const char *format, va_list args)
typedef void (*f_log_function)(int priority, const char *line);
static char log_buf[1024];
static char log_buf[4096];
static size_t log_buf_sz=0;
static void syslog_log_function(int priority, const char *line)
{
@@ -158,11 +158,18 @@ static void android_log_function(int priority, const char *line)
#endif
static void log_buffered(f_log_function log_function, int syslog_priority, const char *format, va_list args)
{
if (vsnprintf(log_buf+log_buf_sz,sizeof(log_buf)-log_buf_sz,format,args)>0)
if (vsnprintf(log_buf+log_buf_sz,sizeof(log_buf)-log_buf_sz-1,format,args)>0)
{
log_buf_sz=strlen(log_buf);
// log when buffer is full or buffer ends with \n
if (log_buf_sz>=(sizeof(log_buf)-1) || (log_buf_sz && log_buf[log_buf_sz-1]=='\n'))
if (log_buf_sz==(sizeof(log_buf)-2))
{
log_buf[log_buf_sz++] = '\n';
log_buf[log_buf_sz] = 0;
log_function(syslog_priority,log_buf);
log_buf_sz = 0;
}
else if (log_buf_sz && log_buf[log_buf_sz-1]=='\n')
{
log_function(syslog_priority,log_buf);
log_buf_sz = 0;
@@ -343,6 +350,10 @@ 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;
dp->filter_ipv4 = dp->filter_ipv6 = true;
}
static void dp_clear_dynamic(struct desync_profile *dp)

View File

@@ -30,7 +30,10 @@
#define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3
#define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60
#define HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT 3
#define HOSTLIST_AUTO_RETRANS_MAXSEQ 65536
#define HOSTLIST_AUTO_RETRANS_MAXSEQ 32768
#define HOSTLIST_AUTO_INCOMING_MAXSEQ 4096
#define HOSTLIST_AUTO_UDP_OUT 4
#define HOSTLIST_AUTO_UDP_IN 1
#define IPCACHE_LIFETIME 7200
@@ -40,7 +43,7 @@
#define BLOB_EXTRA_BYTES 128
// this MSS is used for ipv6 in windows and linux
#define DEFAULT_MSS 1360
#define DEFAULT_MSS 1220
#define RECONSTRUCT_MAX_SIZE 16384
@@ -79,7 +82,9 @@ struct desync_profile
// pointer to autohostlist. NULL if no autohostlist for the profile.
struct hostlist_file *hostlist_auto;
int hostlist_auto_fail_threshold, hostlist_auto_fail_time, hostlist_auto_retrans_threshold;
uint32_t hostlist_auto_retrans_maxseq;
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",
@@ -368,8 +374,10 @@ bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *
// extract 2nd level domains
const char *dhost, *drhost;
if (!FindNLD((uint8_t*)host,strlen(host),2,(const uint8_t**)&dhost,NULL) || !FindNLD((uint8_t*)redirect_host,strlen(redirect_host),2,(const uint8_t**)&drhost,NULL))
if (!FindNLD((uint8_t*)redirect_host,strlen(redirect_host),2,(const uint8_t**)&drhost,NULL))
return false;
if (!FindNLD((uint8_t*)host,strlen(host),2,(const uint8_t**)&dhost,NULL))
return true; // no SLD redirects to SLD
// compare 2nd level domains
return strcasecmp(dhost, drhost)!=0;
@@ -456,9 +464,10 @@ bool IsTLSRecordFull(const uint8_t *data, size_t len)
}
bool IsTLSHandshakeHello(const uint8_t *data, size_t len, uint8_t type, bool bPartialIsOK)
{
// return len >= 1 && (type && data[0]==type || !type && (data[0]==0x01 || data[0]==0x02)) && (bPartialIsOK || IsTLSHandshakeFull(data,len));
return len >= 1 && (type && data[0]==type || !type && (data[0]==0x01 || data[0]==0x02)) && (bPartialIsOK || IsTLSHandshakeFull(data,len));
return len >= 6 &&
(type && data[0]==type || !type && (data[0]==0x01 || data[0]==0x02)) &&
data[4]==0x03 && data[5] <= 0x03 &&
(bPartialIsOK || IsTLSHandshakeFull(data,len));
}
bool IsTLSHandshakeClientHello(const uint8_t *data, size_t len, bool bPartialIsOK)
{
@@ -1308,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;
@@ -1321,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
@@ -1340,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;
}
@@ -1399,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)
{
@@ -1443,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 {