mirror of
https://github.com/bol-van/zapret2.git
synced 2026-03-14 06:13:09 +00:00
Compare commits
901 Commits
v0.7
...
41e26b3ace
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41e26b3ace | ||
|
|
8b6ea88a23 | ||
|
|
59235827c4 | ||
|
|
7073e1fd77 | ||
|
|
340261da72 | ||
|
|
937aa91e5d | ||
|
|
dbf673e24a | ||
|
|
61b0a70fa7 | ||
|
|
d985bb316f | ||
|
|
59b3734643 | ||
|
|
37f45a132f | ||
|
|
4d753ecdc6 | ||
|
|
272f086639 | ||
|
|
d9ae16e56f | ||
|
|
46d4208c76 | ||
|
|
2a4195070f | ||
|
|
8e974e78e2 | ||
|
|
7df42bc486 | ||
|
|
7c12f60e1e | ||
|
|
4c7a3d08d8 | ||
|
|
e146fc24c5 | ||
|
|
6165c13468 | ||
|
|
f7b3946ec2 | ||
|
|
9f29f2c0ae | ||
|
|
c13284b776 | ||
|
|
6e85c9650d | ||
|
|
7f3b5f659f | ||
|
|
8e62b2e743 | ||
|
|
94dfd5fded | ||
|
|
70d8e5ad15 | ||
|
|
a80aed5ccc | ||
|
|
2b35dc8ecd | ||
|
|
75fadab371 | ||
|
|
e70f4a000a | ||
|
|
755c792797 | ||
|
|
b17894eec1 | ||
|
|
9e22ec883c | ||
|
|
f70fb89754 | ||
|
|
e30f99e106 | ||
|
|
fce76e59aa | ||
|
|
1b1c8ddb38 | ||
|
|
5ced6811c8 | ||
|
|
371612b000 | ||
|
|
3c87be3cba | ||
|
|
c642fb3845 | ||
|
|
847e689bfb | ||
|
|
287527092a | ||
|
|
a9514f39f5 | ||
|
|
4b7ff505e4 | ||
|
|
2120264e0b | ||
|
|
178bced5f3 | ||
|
|
ff78968807 | ||
|
|
e4535d2646 | ||
|
|
7c60ad3a7a | ||
|
|
a621edf898 | ||
|
|
2809f8d7e4 | ||
|
|
97819327cd | ||
|
|
eb9a1e9f6b | ||
|
|
6f6850707a | ||
|
|
f702865311 | ||
|
|
6447081a01 | ||
|
|
e4e513ec66 | ||
|
|
47630450bd | ||
|
|
e4129fec63 | ||
|
|
f71ba91e7c | ||
|
|
59e6603b83 | ||
|
|
14a061859f | ||
|
|
9aaa419f68 | ||
|
|
d5231bc4fc | ||
|
|
35cebfba73 | ||
|
|
811d16054b | ||
|
|
a9ee072a14 | ||
|
|
1dbf5ecfe6 | ||
|
|
b210db168f | ||
|
|
5306a043d0 | ||
|
|
b375a94036 | ||
|
|
8b2bff4187 | ||
|
|
827ab7cdcc | ||
|
|
bfa1d8c5dd | ||
|
|
52ea6270f4 | ||
|
|
0fb21856c6 | ||
|
|
48e4d3a6e7 | ||
|
|
6204c74993 | ||
|
|
d981391120 | ||
|
|
7db676e02c | ||
|
|
c91cae0903 | ||
|
|
c06712a0d5 | ||
|
|
2e2f118e10 | ||
|
|
6638140880 | ||
|
|
41bac1833e | ||
|
|
c3b1cc3eb9 | ||
|
|
6f52fb08f9 | ||
|
|
08549b570b | ||
|
|
13daef5167 | ||
|
|
1fd6063cd7 | ||
|
|
5e4f78228e | ||
|
|
2e255ca59f | ||
|
|
565a8abffc | ||
|
|
69f1576f7e | ||
|
|
0917cb21bb | ||
|
|
8f316ae1a2 | ||
|
|
caaf5e7a2e | ||
|
|
dbfbd6e6d3 | ||
|
|
397fe60b5f | ||
|
|
e096ed64bc | ||
|
|
0f2def9bd5 | ||
|
|
85721e4b82 | ||
|
|
0fd9314df9 | ||
|
|
a9e2bfe49c | ||
|
|
bd7a40f5a9 | ||
|
|
bcd50f5215 | ||
|
|
927cca3d44 | ||
|
|
162e8906a6 | ||
|
|
3f7180379b | ||
|
|
5d0af6b058 | ||
|
|
392e1cc1ef | ||
|
|
8a5643851d | ||
|
|
6299a46ab7 | ||
|
|
c5ecc0493d | ||
|
|
7bb8b1d7b3 | ||
|
|
401bd83f82 | ||
|
|
c117c30849 | ||
|
|
6828e7352c | ||
|
|
943e548f93 | ||
|
|
539c329da3 | ||
|
|
4c6902c17c | ||
|
|
9121d949f6 | ||
|
|
64c1f96f80 | ||
|
|
3334786fe3 | ||
|
|
20a0fa671d | ||
|
|
747de07c85 | ||
|
|
6384af6607 | ||
|
|
3046dd8013 | ||
|
|
c80ae95a09 | ||
|
|
d7e5fc1a7c | ||
|
|
97a6b9dd5b | ||
|
|
cfd2df41c4 | ||
|
|
f47f4a0cae | ||
|
|
823a2e2e5d | ||
|
|
0cdbedde74 | ||
|
|
36e243863b | ||
|
|
181395be87 | ||
|
|
fb71a41ea5 | ||
|
|
7f8f64a355 | ||
|
|
7e31dc9d89 | ||
|
|
4a9072a949 | ||
|
|
4b0e3af020 | ||
|
|
d442a38774 | ||
|
|
ede3515fa3 | ||
|
|
831cf02ad5 | ||
|
|
c436470b18 | ||
|
|
56b4ce0b2a | ||
|
|
18b33008af | ||
|
|
c72c48432e | ||
|
|
c5894b0708 | ||
|
|
79b018dd74 | ||
|
|
56cce72dac | ||
|
|
a8b4007386 | ||
|
|
2977c20044 | ||
|
|
d432e770a6 | ||
|
|
0574d609de | ||
|
|
043b85dfb4 | ||
|
|
22b7861603 | ||
|
|
8b24076c20 | ||
|
|
3abc22baf5 | ||
|
|
739c24cdf3 | ||
|
|
5c97563698 | ||
|
|
2ddfe55d9a | ||
|
|
a781f3d1ce | ||
|
|
080655c4c2 | ||
|
|
3434739144 | ||
|
|
740cbfbc34 | ||
|
|
37f0f4589f | ||
|
|
9d7fed4c67 | ||
|
|
2533a3debc | ||
|
|
6e90adad5b | ||
|
|
aa359128bb | ||
|
|
fed07a0249 | ||
|
|
055ae067f9 | ||
|
|
2490ef6951 | ||
|
|
a531da39fd | ||
|
|
b920964ab3 | ||
|
|
7d9f5a4b83 | ||
|
|
b157613b1a | ||
|
|
4081878b36 | ||
|
|
b1fbf5c81a | ||
|
|
04d940e619 | ||
|
|
bd9aec8374 | ||
|
|
e9bffca658 | ||
|
|
001942fe74 | ||
|
|
f5d1108cce | ||
|
|
27d387c76d | ||
|
|
d5306fb97a | ||
|
|
5f87b7670a | ||
|
|
2a2a3e4f73 | ||
|
|
1f99fb49af | ||
|
|
b99b59bbdb | ||
|
|
9128601820 | ||
|
|
584d3b5925 | ||
|
|
eff7e6488a | ||
|
|
27c49bcfe4 | ||
|
|
48fbd39ada | ||
|
|
6eb4970c9b | ||
|
|
ba5cff29f1 | ||
|
|
bd155daa91 | ||
|
|
5de6595ccd | ||
|
|
4253b7b408 | ||
|
|
389a331d83 | ||
|
|
540094baac | ||
|
|
a3c4724542 | ||
|
|
79f33ef75a | ||
|
|
d4c1126961 | ||
|
|
9e378f629d | ||
|
|
227c2e76e3 | ||
|
|
2f74d21923 | ||
|
|
4376aa0cdf | ||
|
|
331e0dcbab | ||
|
|
f1af8cbde9 | ||
|
|
b865591f2a | ||
|
|
384d219597 | ||
|
|
7880782a95 | ||
|
|
d914472542 | ||
|
|
6a32bc46e2 | ||
|
|
8cf0d68d58 | ||
|
|
04134d78ee | ||
|
|
47f6410946 | ||
|
|
a29e159895 | ||
|
|
e5fd657a8a | ||
|
|
faea98da74 | ||
|
|
c8722d1ed9 | ||
|
|
77e405e24d | ||
|
|
7c5dfad8e2 | ||
|
|
b25f16126b | ||
|
|
4970c01344 | ||
|
|
4e412ab2d6 | ||
|
|
a2374f0fcf | ||
|
|
65337446d4 | ||
|
|
be88140bb0 | ||
|
|
27fff3f5c3 | ||
|
|
8ba5739ef2 | ||
|
|
a788975268 | ||
|
|
e441711b05 | ||
|
|
314627d851 | ||
|
|
4560ef6d5b | ||
|
|
431e794356 | ||
|
|
f50bd701f7 | ||
|
|
15f29169d5 | ||
|
|
a106519f1e | ||
|
|
5b016f62e4 | ||
|
|
68c15864a4 | ||
|
|
752cafad7c | ||
|
|
12853b8052 | ||
|
|
1d869650b1 | ||
|
|
12a9bf8b19 | ||
|
|
4ade6f7e82 | ||
|
|
6adb789314 | ||
|
|
78b3baa03f | ||
|
|
90fa71d6d6 | ||
|
|
e33e1a9b89 | ||
|
|
e7f0e79f78 | ||
|
|
8b11d6c279 | ||
|
|
30044e8c61 | ||
|
|
1cffa0f5ec | ||
|
|
8bee9efcf0 | ||
|
|
848221b096 | ||
|
|
fb3bdd9b70 | ||
|
|
ca6d145312 | ||
|
|
01d78e8dc4 | ||
|
|
db050b9ba1 | ||
|
|
b65da8d8db | ||
|
|
1359986d29 | ||
|
|
36ee42bc8c | ||
|
|
a8373a8400 | ||
|
|
33b1e81041 | ||
|
|
577d9e6aba | ||
|
|
3caf1ce10a | ||
|
|
8e67260a23 | ||
|
|
378b1c727d | ||
|
|
14bd4832a4 | ||
|
|
6d8b405bf0 | ||
|
|
00b6d70efc | ||
|
|
ca14fbe9c8 | ||
|
|
c81968b94b | ||
|
|
a2d567c7a0 | ||
|
|
5026199f24 | ||
|
|
68435f64ea | ||
|
|
d84dfaf61d | ||
|
|
4c13c63d27 | ||
|
|
5dde1264ce | ||
|
|
cc989c52ed | ||
|
|
0446b1493b | ||
|
|
97cd8cebca | ||
|
|
2d02eeb578 | ||
|
|
fe318a42e8 | ||
|
|
73c10e3f15 | ||
|
|
17cf260fd0 | ||
|
|
fa15c635bb | ||
|
|
74690047b5 | ||
|
|
d24453da69 | ||
|
|
af200628cd | ||
|
|
76fe7bff82 | ||
|
|
1d1eedbb3b | ||
|
|
274b331825 | ||
|
|
69f900b3da | ||
|
|
da9faabf97 | ||
|
|
60934f5ab8 | ||
|
|
eb7043fc12 | ||
|
|
681c53c3b4 | ||
|
|
65f6923383 | ||
|
|
f0f59261bb | ||
|
|
06cf59d050 | ||
|
|
f0bff44219 | ||
|
|
da0016ed0e | ||
|
|
704c73f821 | ||
|
|
201dd40b46 | ||
|
|
aa13a1f5d2 | ||
|
|
2a3b6f2a8b | ||
|
|
801dec81c8 | ||
|
|
14359afb93 | ||
|
|
372c6748ca | ||
|
|
87d2fcd5a1 | ||
|
|
74ddd4f9d2 | ||
|
|
6b7507deb5 | ||
|
|
f8156a3d38 | ||
|
|
67a8ee47e3 | ||
|
|
93d81ca4b2 | ||
|
|
3d9a36600b | ||
|
|
c3adb3f045 | ||
|
|
f919533873 | ||
|
|
17bdfe16b1 | ||
|
|
bc0102fbdc | ||
|
|
10d72b3242 | ||
|
|
9dd14dfc7c | ||
|
|
10201f1abf | ||
|
|
236550918b | ||
|
|
72a269e88d | ||
|
|
d3199eebd3 | ||
|
|
ffcb14726d | ||
|
|
aa5a1f4183 | ||
|
|
ca186a6566 | ||
|
|
dced388652 | ||
|
|
1f7d10bf5b | ||
|
|
6b1b4adddb | ||
|
|
cfe7b76352 | ||
|
|
62fd0dc432 | ||
|
|
050a01bda2 | ||
|
|
4c5d84c19e | ||
|
|
d430b4775d | ||
|
|
807565968e | ||
|
|
e062b1795e | ||
|
|
3417e50438 | ||
|
|
70f5a88ec0 | ||
|
|
4b3fba3fb2 | ||
|
|
9cded5448a | ||
|
|
2302ac6949 | ||
|
|
0be76b902e | ||
|
|
fa89e011fb | ||
|
|
622a81001d | ||
|
|
4d793b73a4 | ||
|
|
a47b6a529b | ||
|
|
7c320c8d57 | ||
|
|
b18f0770c8 | ||
|
|
f7fc845014 | ||
|
|
2c1a885a07 | ||
|
|
9eb308d84c | ||
|
|
3e724c3810 | ||
|
|
c179d55d88 | ||
|
|
3f1af1441e | ||
|
|
4c1b2b65f3 | ||
|
|
918258413f | ||
|
|
e6206c5a5f | ||
|
|
f93c6de772 | ||
|
|
5a7e2b1ca2 | ||
|
|
ca8104c72a | ||
|
|
3aad1f9ed9 | ||
|
|
fd288d5e7d | ||
|
|
349fe3f7d7 | ||
|
|
4554b7c15b | ||
|
|
0b595ae3a8 | ||
|
|
3e69e1b8c1 | ||
|
|
02b895910b | ||
|
|
b2a53e9c64 | ||
|
|
a626cfce8a | ||
|
|
ebcbfc37ba | ||
|
|
33d3c94b68 | ||
|
|
d55dbb7717 | ||
|
|
cb82be9eab | ||
|
|
024d36acc4 | ||
|
|
08c6151a4c | ||
|
|
520317dc3c | ||
|
|
6bc0bf1b97 | ||
|
|
d18fec9053 | ||
|
|
e60e5a0578 | ||
|
|
84576a7039 | ||
|
|
7957a0a425 | ||
|
|
7ba4110416 | ||
|
|
4babaef6a8 | ||
|
|
872e37d160 | ||
|
|
a8219f4897 | ||
|
|
36267b7e9b | ||
|
|
99a7f06976 | ||
|
|
3617b8934f | ||
|
|
8e6387a6df | ||
|
|
3bc0e8e350 | ||
|
|
7f12334872 | ||
|
|
0f42ff1731 | ||
|
|
801328dc02 | ||
|
|
fdb9c9be60 | ||
|
|
5e89db0c7b | ||
|
|
0e95de6083 | ||
|
|
3ec585c97e | ||
|
|
577959f442 | ||
|
|
36731cd9b5 | ||
|
|
b3b8133c39 | ||
|
|
5f96ce1099 | ||
|
|
2088f593d4 | ||
|
|
03152ba76f | ||
|
|
f94d1b1d16 | ||
|
|
790a2ca355 | ||
|
|
f318397726 | ||
|
|
5a116cf9be | ||
|
|
d40f05865b | ||
|
|
e47603281c | ||
|
|
8ba58c8f16 | ||
|
|
2def9397a0 | ||
|
|
a61895778b | ||
|
|
a622061b45 | ||
|
|
1bbd342ff2 | ||
|
|
84f978cee4 | ||
|
|
dd3cffca5f | ||
|
|
b699e5d9ec | ||
|
|
e6591575fe | ||
|
|
ca7569f68a | ||
|
|
3a16523399 | ||
|
|
2fd172118c | ||
|
|
c43574d056 | ||
|
|
22d4df73f6 | ||
|
|
23d6cddb30 | ||
|
|
c3b5d5e9ed | ||
|
|
20856321c3 | ||
|
|
75f3c7eac3 | ||
|
|
129461dc45 | ||
|
|
91a3badc67 | ||
|
|
ff15bcceae | ||
|
|
61b20f86a7 | ||
|
|
2de8809ead | ||
|
|
c77e8f799f | ||
|
|
4cdf498a14 | ||
|
|
4bbfc3081d | ||
|
|
1099cf013d | ||
|
|
cb85f6e672 | ||
|
|
823f4a6fb6 | ||
|
|
05647e84ef | ||
|
|
8bc74d0c4f | ||
|
|
0eb6cc9722 | ||
|
|
13594401c6 | ||
|
|
2983c681d7 | ||
|
|
68eefd9dd7 | ||
|
|
73f6f7c522 | ||
|
|
df83a29b98 | ||
|
|
9881cc4da2 | ||
|
|
44f8ad6747 | ||
|
|
c651367d6a | ||
|
|
90f88271c5 | ||
|
|
9ba8d6cbdf | ||
|
|
27efbb37d7 | ||
|
|
d725bd8fd7 | ||
|
|
0ef50d04dc | ||
|
|
fdae4b1812 | ||
|
|
d0644f6160 | ||
|
|
b4f1765574 | ||
|
|
8454d48fcd | ||
|
|
70d7a77d06 | ||
|
|
2a48f82feb | ||
|
|
c5d997ce48 | ||
|
|
c950edb380 | ||
|
|
0d96b03f49 | ||
|
|
9772641813 | ||
|
|
7307a03ff7 | ||
|
|
b529198f24 | ||
|
|
5f5cfb434c | ||
|
|
2f1aa5734e | ||
|
|
062360f3f3 | ||
|
|
7122808425 | ||
|
|
515921522e | ||
|
|
c0ce825a95 | ||
|
|
c4b23d21ce | ||
|
|
0847d9f140 | ||
|
|
b239690e33 | ||
|
|
4f6510daf1 | ||
|
|
0cad2329a1 | ||
|
|
24d9eb1fe2 | ||
|
|
f98445d36b | ||
|
|
7278bb1b87 | ||
|
|
5b58997e3e | ||
|
|
93a6487eb5 | ||
|
|
fdca797671 | ||
|
|
bb9e78e8fb | ||
|
|
2a15a1a778 | ||
|
|
bf89b415bb | ||
|
|
735936efc5 | ||
|
|
9d09d8adcc | ||
|
|
3874e16075 | ||
|
|
cbb05967ba | ||
|
|
665bd5f318 | ||
|
|
fa1d7c30c3 | ||
|
|
940f94162d | ||
|
|
60108bf378 | ||
|
|
5a68245e32 | ||
|
|
b2dbdd4dd7 | ||
|
|
5bc65c3b91 | ||
|
|
6bf7f2c7c0 | ||
|
|
44a80abb3f | ||
|
|
89f0f39b83 | ||
|
|
ad6f1db149 | ||
|
|
9154fe1677 | ||
|
|
5e63a0f5c5 | ||
|
|
0521053991 | ||
|
|
7b7ed1ad60 | ||
|
|
2915647c63 | ||
|
|
958a4e918b | ||
|
|
cb332dad74 | ||
|
|
17e9e0a8e6 | ||
|
|
78b348a193 | ||
|
|
8103a02689 | ||
|
|
a2dedc45c0 | ||
|
|
f0d3a63df9 | ||
|
|
c6ca25a656 | ||
|
|
71b87f749d | ||
|
|
3d756c9702 | ||
|
|
13864fe5c5 | ||
|
|
cc2601af2f | ||
|
|
07319a329e | ||
|
|
52f5c2697b | ||
|
|
6b0dde5643 | ||
|
|
e42265e071 | ||
|
|
939f7a9558 | ||
|
|
b62ebd8fcb | ||
|
|
521fafc05d | ||
|
|
419d6769bd | ||
|
|
dde3f59d32 | ||
|
|
78e1fb85ac | ||
|
|
f73790b871 | ||
|
|
33f3378094 | ||
|
|
af7a6f6c10 | ||
|
|
9cc348e5bd | ||
|
|
8628c34941 | ||
|
|
eec9f3e87c | ||
|
|
e4a8f51775 | ||
|
|
fb962df188 | ||
|
|
173dcd47d1 | ||
|
|
3439dc4f21 | ||
|
|
6e04162a20 | ||
|
|
883a3d6233 | ||
|
|
e8cde6b0a2 | ||
|
|
43872a21a6 | ||
|
|
ff2c3e81f9 | ||
|
|
bcbfb45c53 | ||
|
|
fa6a75f139 | ||
|
|
e96c06598c | ||
|
|
58320aecbe | ||
|
|
ba526b75e1 | ||
|
|
b9321619fc | ||
|
|
d1a489a196 | ||
|
|
cf91697dfb | ||
|
|
401886bf32 | ||
|
|
8baf81a840 | ||
|
|
417cd8335a | ||
|
|
5a9d40ad3f | ||
|
|
af0be0fd94 | ||
|
|
68e0c367c9 | ||
|
|
0969d22391 | ||
|
|
94daca8ced | ||
|
|
1982984a86 | ||
|
|
6a520f508a | ||
|
|
70d0dd5d79 | ||
|
|
4ca0f6b574 | ||
|
|
76e85d8969 | ||
|
|
f458a76880 | ||
|
|
6077d363ec | ||
|
|
c70f114c3a | ||
|
|
2c037dca73 | ||
|
|
fe2fc0337f | ||
|
|
b3a86d0d8a | ||
|
|
5618be9a71 | ||
|
|
715ae4bf1c | ||
|
|
f44b6bf769 | ||
|
|
e75857c448 | ||
|
|
bc008e2cf3 | ||
|
|
752226208b | ||
|
|
9e2222549e | ||
|
|
b0686b16f7 | ||
|
|
d5b2c41daa | ||
|
|
46a7632f59 | ||
|
|
0642969a2d | ||
|
|
13af2ec1be | ||
|
|
50a1bb72d9 | ||
|
|
1696f1b552 | ||
|
|
b0ce5c0c1b | ||
|
|
87943846d9 | ||
|
|
8b359d0410 | ||
|
|
0430d9d9cd | ||
|
|
efcc1477dd | ||
|
|
100fff0461 | ||
|
|
1d14f8b0a4 | ||
|
|
6e5c6511d3 | ||
|
|
491a24d671 | ||
|
|
505e8ff82c | ||
|
|
1bbc56dc1b | ||
|
|
ad60550bf3 | ||
|
|
3043963e28 | ||
|
|
664bc60175 | ||
|
|
815801a7db | ||
|
|
05f54086cf | ||
|
|
b7a5f0410f | ||
|
|
da8bb9f5b8 | ||
|
|
9e52d767d1 | ||
|
|
3ff06303cb | ||
|
|
2a5c036909 | ||
|
|
a6e11540ff | ||
|
|
347c35e588 | ||
|
|
ea28460f1d | ||
|
|
0ac5df9d0e | ||
|
|
63767929a0 | ||
|
|
026c832f3f | ||
|
|
53ef85773e | ||
|
|
c41353cb8a | ||
|
|
d2f6c18adf | ||
|
|
00d1406791 | ||
|
|
a38acae652 | ||
|
|
90a991b5ee | ||
|
|
686721f96a | ||
|
|
479b067f1a | ||
|
|
ea1f34c833 | ||
|
|
b4fe028cb7 | ||
|
|
39c3640477 | ||
|
|
2236a95d49 | ||
|
|
8bb03d68b5 | ||
|
|
7b2a9a26ed | ||
|
|
b0ae1ac6f8 | ||
|
|
29c1d1f164 | ||
|
|
7cedbc5630 | ||
|
|
ccd943a02b | ||
|
|
49dc116c4b | ||
|
|
f70107fad3 | ||
|
|
40e9edcdcb | ||
|
|
905677b7ac | ||
|
|
87b7b644c7 | ||
|
|
2b410318ff | ||
|
|
afee286d91 | ||
|
|
f223a3e7e9 | ||
|
|
258e353a52 | ||
|
|
934d6e3e91 | ||
|
|
630fb94466 | ||
|
|
87617d379b | ||
|
|
1b6b3306aa | ||
|
|
2cf74b3ed6 | ||
|
|
0cd6f97b68 | ||
|
|
3e2ead29da | ||
|
|
ebffdfad08 | ||
|
|
205a3ca528 | ||
|
|
a014984f65 | ||
|
|
c62f49fa86 | ||
|
|
5bf3f4029d | ||
|
|
b475f11c7c | ||
|
|
021913aba2 | ||
|
|
154d7d9c60 | ||
|
|
7d6ddd557d | ||
|
|
600345b3ec | ||
|
|
7923535849 | ||
|
|
e8d8e3f7d2 | ||
|
|
c6e6b51077 | ||
|
|
c1acca07c3 | ||
|
|
4cc52b9d24 | ||
|
|
0c4ef51b2a | ||
|
|
1027cb666d | ||
|
|
1920bbf862 | ||
|
|
1a80e0cc0c | ||
|
|
ebcd07b865 | ||
|
|
eaecce9630 | ||
|
|
17b7eb7c4b | ||
|
|
12838003f8 | ||
|
|
fa820b3e98 | ||
|
|
af867002f4 | ||
|
|
c6bc68d414 | ||
|
|
801cacef58 | ||
|
|
0df18df3f1 | ||
|
|
4d9108822c | ||
|
|
72f0b61cc0 | ||
|
|
99ea6e6fe0 | ||
|
|
99482d06d4 | ||
|
|
65faaffe78 | ||
|
|
81b2aa9d02 | ||
|
|
e07239e717 | ||
|
|
a5ca736ad7 | ||
|
|
320f938418 | ||
|
|
5e53ecfacb | ||
|
|
d46edfdd55 | ||
|
|
ec6e438144 | ||
|
|
5b06f0b2a7 | ||
|
|
ec1f5b5eff | ||
|
|
774d9b79c0 | ||
|
|
176ccb6b8a | ||
|
|
f0e31c0fd1 | ||
|
|
7c3f1080e0 | ||
|
|
3f760c778b | ||
|
|
1b6b4c6b42 | ||
|
|
6361a3798a | ||
|
|
83feefdc18 | ||
|
|
6d249528e4 | ||
|
|
cf8874c4f5 | ||
|
|
82955888b8 | ||
|
|
eec1461867 | ||
|
|
5e5dd241d4 | ||
|
|
8f53a44f7e | ||
|
|
03fd5acc95 | ||
|
|
b40f5511d1 | ||
|
|
89a662ed0a | ||
|
|
c79822e5ef | ||
|
|
3fd50eefb7 | ||
|
|
2cdc45703a | ||
|
|
5c77e78ad9 | ||
|
|
48d59b436c | ||
|
|
d829464843 | ||
|
|
0fb44db47c | ||
|
|
77cd246540 | ||
|
|
b4d0ea465b | ||
|
|
89cbed43dc | ||
|
|
27ba59fa7f | ||
|
|
df30a86305 | ||
|
|
02349dcb1d | ||
|
|
7bcca64f08 | ||
|
|
14bf1ce69b | ||
|
|
0034e75321 | ||
|
|
f6c9f8b151 | ||
|
|
76acf483f9 | ||
|
|
e7e175dd82 | ||
|
|
68ac46d1d2 | ||
|
|
2ecd34cbca | ||
|
|
b5b1f71fcc | ||
|
|
f5f7de4086 | ||
|
|
a331d59d33 | ||
|
|
0a6d066e92 | ||
|
|
1216ef0364 | ||
|
|
52e38ee687 | ||
|
|
fd53a54cf3 | ||
|
|
c6b7e1fc43 | ||
|
|
a7a1520b40 | ||
|
|
04881b10b1 | ||
|
|
561e5e2718 | ||
|
|
e83e127c15 | ||
|
|
3590861ffe | ||
|
|
a12307d7f9 | ||
|
|
25a9f9e426 | ||
|
|
f4644e2a47 | ||
|
|
b9a0d42815 | ||
|
|
f76beba434 | ||
|
|
60b6ec2f49 | ||
|
|
ce95210d1c | ||
|
|
953d92b177 | ||
|
|
4d9b4c9ad8 | ||
|
|
ee7b72dc66 | ||
|
|
8eb588d6a4 | ||
|
|
08e1f8fba1 | ||
|
|
454eedeb36 | ||
|
|
7e761b3f03 | ||
|
|
3dd51ee3b1 | ||
|
|
07b1356c6c | ||
|
|
23445785c9 | ||
|
|
f4a7fe3aaf | ||
|
|
6d31036ca1 | ||
|
|
5ceb3aa301 | ||
|
|
7fd602885f | ||
|
|
af75c3d63d | ||
|
|
cb9789668f | ||
|
|
c16508e2e4 | ||
|
|
912eb1217a | ||
|
|
3a328089a3 | ||
|
|
4c76444b2d | ||
|
|
403413bb26 | ||
|
|
8ea6a17942 | ||
|
|
15731d6135 | ||
|
|
8255481787 | ||
|
|
d2a919f71d | ||
|
|
915130aed9 | ||
|
|
901ffdfe5a | ||
|
|
8caaf85b36 | ||
|
|
1dc5e23a41 | ||
|
|
ee859db268 | ||
|
|
37f7fbbdec | ||
|
|
81f6937187 | ||
|
|
cbf5be50d1 | ||
|
|
1966ea2298 | ||
|
|
d96350d2c7 | ||
|
|
5cb96559d0 | ||
|
|
dffba7cd13 | ||
|
|
5ad122da40 | ||
|
|
54871f4ef8 | ||
|
|
d06e4f4c82 | ||
|
|
322b050e45 | ||
|
|
5cb9cfc820 | ||
|
|
ede260d4fa | ||
|
|
9a7de03830 | ||
|
|
b9b14f254a | ||
|
|
653ed92cf8 | ||
|
|
0d99c68b1b | ||
|
|
6c75dcc002 | ||
|
|
b76e1f65a3 | ||
|
|
de8845b89d | ||
|
|
f1eae764ab | ||
|
|
03c650b33c | ||
|
|
64b12c51e5 | ||
|
|
2d8e031904 | ||
|
|
28f0cd6e73 | ||
|
|
9a9179a23b | ||
|
|
48123bf1f7 | ||
|
|
ece4e52676 | ||
|
|
1d24d1e040 | ||
|
|
d0fd6b4868 | ||
|
|
328408fa30 | ||
|
|
0343bb248d | ||
|
|
e4dd1574b8 | ||
|
|
1e3486ee14 | ||
|
|
efe7470732 | ||
|
|
8acd5690f4 | ||
|
|
c2e3176a46 | ||
|
|
658252d46a | ||
|
|
5aaf7b3d6c | ||
|
|
031ac7616d | ||
|
|
098417d19f | ||
|
|
2f0a74a11e | ||
|
|
40c37c3448 | ||
|
|
77fb530120 | ||
|
|
faa0274521 | ||
|
|
8a253d3d95 | ||
|
|
0aac2965c1 | ||
|
|
d1128a8bc6 | ||
|
|
e016fc0e42 | ||
|
|
f48ea2f6a7 | ||
|
|
2ab71ab895 | ||
|
|
736e0ba3d4 | ||
|
|
f2ae880c11 | ||
|
|
019f3089c6 | ||
|
|
30d28488c9 | ||
|
|
5bcec4aada | ||
|
|
886fbabcfc | ||
|
|
cd8dbf2a2b | ||
|
|
002742bd03 | ||
|
|
dc2c707c3c | ||
|
|
9630d0a9df | ||
|
|
f4c4d5e558 | ||
|
|
7b37880954 | ||
|
|
6b7738ac16 | ||
|
|
8dec014b50 | ||
|
|
b0ee32f3dc | ||
|
|
0e770ff46d | ||
|
|
14b3aef030 | ||
|
|
004c583595 | ||
|
|
c4818a6a32 | ||
|
|
58d57fed01 | ||
|
|
d6b73fe7e0 | ||
|
|
4867838fce | ||
|
|
4b2551509f | ||
|
|
ed6acb36a1 | ||
|
|
26b80e80b6 | ||
|
|
79b776b5a9 | ||
|
|
3b251b9ee6 | ||
|
|
8c65a966d9 | ||
|
|
9da0b13aa3 | ||
|
|
d7fd491121 | ||
|
|
c60ef399ec | ||
|
|
2abab21e4b | ||
|
|
6190babb99 | ||
|
|
7ce0b4a996 | ||
|
|
053556fe2d | ||
|
|
52571045fe | ||
|
|
db875ed1d4 | ||
|
|
e828864811 | ||
|
|
4404127fa3 | ||
|
|
13e81e4b6f | ||
|
|
a631add2d9 | ||
|
|
26b9b63a20 | ||
|
|
90489fad2f | ||
|
|
d93c243d21 | ||
|
|
65235d71d7 | ||
|
|
fc01e6715f | ||
|
|
1a33d68998 | ||
|
|
dfaa475d2a | ||
|
|
743018423a | ||
|
|
762023f201 | ||
|
|
a296b93b7a | ||
|
|
1c9b3aa1bc | ||
|
|
565fa8e337 | ||
|
|
9fcecd07d1 | ||
|
|
652e271877 | ||
|
|
fc7ed4f4a8 | ||
|
|
e9e5bdc860 | ||
|
|
a2b8300219 | ||
|
|
dfdcfbdf51 | ||
|
|
170ec372fb | ||
|
|
3f073908a6 |
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1,5 +1,7 @@
|
||||
* text=auto eol=lf
|
||||
*.cmd eol=crlf
|
||||
*.bat eol=crlf
|
||||
*.manifest eol=crlf
|
||||
*.rc eol=crlf
|
||||
init.d/windivert.filter.examples/** eol=crlf
|
||||
files/** binary
|
||||
|
||||
8
.github/ISSUE_TEMPLATE/issue-warning.md
vendored
8
.github/ISSUE_TEMPLATE/issue-warning.md
vendored
@@ -11,8 +11,14 @@ Issues - это место для обращений к разработчику
|
||||
Discussions - место для обсуждения вопросов между пользователями.
|
||||
|
||||
Все, что выходит за рамки багов и технически грамотных предложений, идей,
|
||||
вопросы типа "как мне это запустить", "что нажать", "что вписать" - будет безжалостно удаляться.
|
||||
вопросы типа "как мне это запустить", "что нажать", "что вписать", "перестало открываться" - будет безжалостно удаляться.
|
||||
Если вы не знаете как пользоваться, для вас что-то сложно, здесь - не место обучению программе или linux и не место для вопросов подобного рода.
|
||||
Поймите, пожалуйста, что zapret - это инструмент, а не готовое решение для пользователя. В его функциях нет кнопки "открыть сайты", поэтому
|
||||
если они перестали открываться - это не issue. Функцию "открыть сайты" дают только сборки - ищите их и все вопросы адресуйте туда.
|
||||
Если вы игнорируете данное требование, вы не достигните своих целей , а только добавите желания удалить ваш issue или при настойчивости забанить.
|
||||
Идите в дискуссии, не захламляйте issues.
|
||||
|
||||
Так же будут немедленно удаляться любые issue, связанные с реакцией антивирусов. При агрессии или настойчивости - бан. (подсказка : вирусов нет, удаляйте если не верите)
|
||||
|
||||
Here is the place for bugs only. All questions, especially user-like questions (non-technical) go to Discussions.
|
||||
There're also no viruses here. All virus claims and everyting non-technical and non-bugs will be instantly deleted, closed or moved to Discussions.
|
||||
|
||||
102
.github/workflows/build.yml
vendored
102
.github/workflows/build.yml
vendored
@@ -26,32 +26,20 @@ jobs:
|
||||
tool: aarch64-unknown-linux-musl
|
||||
- arch: arm
|
||||
tool: arm-unknown-linux-musleabi
|
||||
# - arch: armhf
|
||||
# tool: arm-unknown-linux-musleabihf
|
||||
# - arch: armv7
|
||||
# tool: armv7-unknown-linux-musleabi
|
||||
# - arch: armv7hf
|
||||
# tool: armv7-unknown-linux-musleabihf
|
||||
# - arch: mips64el
|
||||
# tool: mips64el-unknown-linux-musl
|
||||
- arch: mips64
|
||||
tool: mips64-unknown-linux-musl
|
||||
# - arch: mipsel
|
||||
# tool: mipsel-unknown-linux-musl
|
||||
- arch: mipselsf
|
||||
tool: mipsel-unknown-linux-muslsf
|
||||
# - arch: mips
|
||||
# tool: mips-unknown-linux-musl
|
||||
- arch: mipssf
|
||||
tool: mips-unknown-linux-muslsf
|
||||
# - arch: ppc64
|
||||
# tool: powerpc64-unknown-linux-musl
|
||||
- arch: ppc
|
||||
tool: powerpc-unknown-linux-musl
|
||||
- arch: x86
|
||||
tool: i586-unknown-linux-musl
|
||||
- arch: x86_64
|
||||
tool: x86_64-unknown-linux-musl
|
||||
- arch: riscv64
|
||||
tool: riscv64-unknown-linux-musl
|
||||
- arch: lexra
|
||||
tool: mips-linux
|
||||
dir: rsdk-4.6.4-5281-EB-3.10-0.9.33-m32ub-20141001
|
||||
@@ -69,17 +57,17 @@ jobs:
|
||||
env:
|
||||
ARCH: ${{ matrix.arch }}
|
||||
TOOL: ${{ matrix.tool }}
|
||||
REPO: ${{ matrix.arch == 'lexra' && matrix.repo || 'spvkgn/musl-cross' }}
|
||||
REPO: ${{ matrix.arch == 'lexra' && matrix.repo || 'bol-van/musl-cross' }}
|
||||
DIR: ${{ matrix.arch == 'lexra' && matrix.dir || matrix.tool }}
|
||||
run: |
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt update -qq
|
||||
if [[ "$ARCH" == lexra ]]; then
|
||||
sudo apt install -y libcap-dev libc6:i386 zlib1g:i386
|
||||
sudo apt install -y pigz libcap-dev libc6:i386 zlib1g:i386
|
||||
URL=https://github.com/$REPO/raw/refs/heads/master/$DIR.txz
|
||||
else
|
||||
# luajit buildvm requires 32 bit executable on host platform for 32 bit cross targets
|
||||
sudo apt install -y libcap-dev libc6-dev gcc-multilib
|
||||
sudo apt install -y pigz libcap-dev libc6-dev gcc-multilib
|
||||
URL=https://github.com/$REPO/releases/download/latest/$TOOL.tar.xz
|
||||
fi
|
||||
mkdir -p $HOME/tools
|
||||
@@ -93,11 +81,13 @@ jobs:
|
||||
CFLAGS: ${{ matrix.env.CFLAGS != '' && matrix.env.CFLAGS || null }}
|
||||
LDFLAGS: ${{ matrix.env.LDFLAGS != '' && matrix.env.LDFLAGS || null }}
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
LUA_VER: 5.4
|
||||
LUA_RELEASE: 5.4.8
|
||||
LUA_VER: 5.5
|
||||
LUA_RELEASE: 5.5.0
|
||||
LUAJIT_VER: 2.1
|
||||
LUAJIT_RELEASE: 2.1-20250826
|
||||
LUAJIT_LUAVER: 5.1
|
||||
MINSIZE: -flto=auto -ffunction-sections -fdata-sections
|
||||
LDMINSIZE: -Wl,--gc-sections -flto=auto
|
||||
run: |
|
||||
DEPS_DIR=$GITHUB_WORKSPACE/deps
|
||||
export CC="$TARGET-gcc"
|
||||
@@ -107,13 +97,19 @@ jobs:
|
||||
export STRIP=$TARGET-strip
|
||||
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
|
||||
export STAGING_DIR=$RUNNER_TEMP
|
||||
if [ "$ARCH" = lexra ]; then
|
||||
OPTIMIZE=-Os
|
||||
else
|
||||
OPTIMIZE=-Oz
|
||||
fi
|
||||
MINSIZE="$OPTIMIZE $MINSIZE"
|
||||
|
||||
if [[ "$ARCH" == lexra ]] || [[ "$ARCH" == ppc ]] || [[ "$ARCH" == x86 ]]; then
|
||||
if [[ "$ARCH" == lexra ]] || [[ "$ARCH" == riscv64 ]] || [[ "$ARCH" == x86 ]] ; then
|
||||
# use classic lua
|
||||
wget -qO- https://www.lua.org/ftp/lua-${LUA_RELEASE}.tar.gz | tar -xz
|
||||
(
|
||||
cd lua-${LUA_RELEASE}
|
||||
make CC=$CC CFLAGS="-Os -flto=auto $CFLAGS" linux -j$(nproc)
|
||||
make CC=$CC AR="$AR rc" CFLAGS="$MINSIZE $CFLAGS" LDFLAGS="$LDMINSIZE $LDFLAGS" linux -j$(nproc)
|
||||
make install INSTALL_TOP=$DEPS_DIR INSTALL_BIN=$DEPS_DIR/bin INSTALL_INC=$DEPS_DIR/include/lua${LUA_VER} INSTALL_LIB=$DEPS_DIR/lib
|
||||
)
|
||||
LJIT=0
|
||||
@@ -131,7 +127,7 @@ jobs:
|
||||
esac
|
||||
(
|
||||
cd luajit2-*
|
||||
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC="$HOSTCC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP CFLAGS="-Os -s -flto=auto $CFLAGS" -j$(nproc)
|
||||
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC="$HOSTCC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP TARGET_CFLAGS="$MINSIZE $CFLAGS" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS" -j$(nproc)
|
||||
make install PREFIX= DESTDIR=$DEPS_DIR
|
||||
)
|
||||
LJIT=1
|
||||
@@ -147,7 +143,8 @@ jobs:
|
||||
for i in libmnl libnfnetlink libnetfilter_queue ; do
|
||||
(
|
||||
cd $i-*
|
||||
CFLAGS="-Os -flto=auto $CFLAGS" \
|
||||
CFLAGS="$MINSIZE $CFLAGS" \
|
||||
LDFLAGS="$LDMINSIZE $LDFLAGS" \
|
||||
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
|
||||
make install -j$(nproc) DESTDIR=$DEPS_DIR
|
||||
)
|
||||
@@ -159,7 +156,7 @@ jobs:
|
||||
xargs -I{} wget -qO- https://github.com/madler/zlib/archive/refs/tags/{}.tar.gz | tar -xz
|
||||
(
|
||||
cd zlib-*
|
||||
CFLAGS="-Os -flto=auto $CFLAGS" \
|
||||
CFLAGS="$MINSIZE $CFLAGS" \
|
||||
./configure --prefix= --static
|
||||
make install -j$(nproc) DESTDIR=$DEPS_DIR
|
||||
)
|
||||
@@ -170,6 +167,7 @@ jobs:
|
||||
install -Dm644 -t $DEPS_DIR/include/sys /usr/include/x86_64-linux-gnu/sys/queue.h /usr/include/sys/capability.h
|
||||
|
||||
# zapret2
|
||||
OPTIMIZE=$OPTIMIZE \
|
||||
CFLAGS="-DZAPRET_GH_VER=${{ github.ref_name }} -DZAPRET_GH_HASH=${{ github.sha }} -static-libgcc -static -I$DEPS_DIR/include $CFLAGS" \
|
||||
LDFLAGS="-L$DEPS_DIR/lib $LDFLAGS" \
|
||||
make -C zapret2 LUA_JIT=$LJIT LUA_CFLAGS="$LCFLAGS" LUA_LIB="$LLIB" -j$(nproc)
|
||||
@@ -220,6 +218,8 @@ jobs:
|
||||
LUAJIT_VER: 2.1
|
||||
LUAJIT_RELEASE: 2.1-20250826
|
||||
LUAJIT_LUAVER: 5.1
|
||||
MINSIZE: -Oz -flto=auto -ffunction-sections -fdata-sections
|
||||
LDMINSIZE: -Wl,--gc-sections -flto=auto
|
||||
run: |
|
||||
DEPS_DIR=$GITHUB_WORKSPACE/deps
|
||||
export TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64
|
||||
@@ -242,7 +242,7 @@ jobs:
|
||||
esac
|
||||
(
|
||||
cd luajit2-*
|
||||
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC="$HOSTCC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP CFLAGS="-Os -flto=auto $CFLAGS" -j$(nproc)
|
||||
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC="$HOSTCC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP TARGET_CFLAGS="$MINSIZE $CFLAGS" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS" -j$(nproc)
|
||||
make install PREFIX= DESTDIR=$DEPS_DIR
|
||||
)
|
||||
LJIT=1
|
||||
@@ -258,7 +258,8 @@ jobs:
|
||||
for i in libmnl libnfnetlink libnetfilter_queue ; do
|
||||
(
|
||||
cd $i-*
|
||||
CFLAGS="-Os -flto=auto -Wno-implicit-function-declaration" \
|
||||
CFLAGS="$MINSIZE -Wno-implicit-function-declaration $CFLAGS" \
|
||||
LDFLAGS="$LDMINSIZE $LDFLAGS" \
|
||||
./configure --prefix= --host=$TARGET --enable-static --disable-shared --disable-dependency-tracking
|
||||
make install -j$(nproc) DESTDIR=$DEPS_DIR
|
||||
)
|
||||
@@ -314,12 +315,14 @@ jobs:
|
||||
TARGET: ${{ matrix.target }}
|
||||
ARCH: ${{ matrix.arch }}
|
||||
CC: ${{ matrix.target }}-freebsd11-clang
|
||||
MINSIZE: -Oz -flto=auto -ffunction-sections -fdata-sections
|
||||
LDMINSIZE: -Wl,--gc-sections -flto=auto
|
||||
run: |
|
||||
|
||||
wget -qO- https://github.com/openresty/luajit2/archive/refs/tags/v${LUAJIT_RELEASE}.tar.gz | tar -xz
|
||||
(
|
||||
cd luajit2-*
|
||||
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC=gcc CC=$CC CFLAGS="-Os -flto=auto $CFLAGS"
|
||||
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC=gcc CC=$CC TARGET_CFLAGS="$MINSIZE $CFLAGS" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS"
|
||||
make install PREFIX= DESTDIR=$DEPS_DIR
|
||||
)
|
||||
|
||||
@@ -390,8 +393,8 @@ jobs:
|
||||
uses: cygwin/cygwin-install-action@v4
|
||||
with:
|
||||
platform: ${{ matrix.arch }}
|
||||
site: ${{ matrix.arch == 'x86_64' && 'http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2024/01/30/231215' || null }}
|
||||
check-sig: ${{ matrix.arch == 'x86_64' && 'false' || null }}
|
||||
site: ${{ matrix.arch == 'x86_64' && 'http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2024/01/30/231215' || 'http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/2022/11/23/063457' }}
|
||||
check-sig: 'false'
|
||||
packages: >-
|
||||
gcc-core
|
||||
make
|
||||
@@ -424,13 +427,15 @@ jobs:
|
||||
- name: Build luajit
|
||||
env:
|
||||
LUAJIT_RELEASE: 2.1-20250826
|
||||
MINSIZE: -Os -flto=auto -ffunction-sections -fdata-sections
|
||||
LDMINSIZE: -Wl,--gc-sections -flto=auto
|
||||
shell: C:\cygwin\bin\bash.exe -eo pipefail '{0}'
|
||||
run: >-
|
||||
export MAKEFLAGS=-j$(nproc) &&
|
||||
wget -q https://github.com/openresty/luajit2/archive/refs/tags/v${LUAJIT_RELEASE}.tar.gz &&
|
||||
tar -xzf v${LUAJIT_RELEASE}.tar.gz &&
|
||||
rm -f v${LUAJIT_RELEASE}.tar.gz &&
|
||||
make -C luajit2-${LUAJIT_RELEASE} BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI CFLAGS="-Os -s" &&
|
||||
make -C luajit2-${LUAJIT_RELEASE} BUILDMODE=static XCFLAGS="-DLUAJIT_DISABLE_FFI -ffat-lto-objects" TARGET_CFLAGS="$MINSIZE $CFLAGS" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS" &&
|
||||
make -C luajit2-${LUAJIT_RELEASE} install
|
||||
|
||||
- name: Build winws
|
||||
@@ -485,17 +490,28 @@ jobs:
|
||||
pattern: zapret2-*
|
||||
|
||||
- name: Install upx
|
||||
uses: crazy-max/ghaction-upx@v3
|
||||
with:
|
||||
install-only: true
|
||||
version: v4.2.4
|
||||
shell: bash
|
||||
env:
|
||||
VER_OLD: 4.2.4
|
||||
VER_NEW: 5.1.0
|
||||
run: |
|
||||
# old upx works for old kernels like 2.6.26
|
||||
# new upx crashes on ~<3.10 but required for riscv64
|
||||
curl -Lo - https://github.com/upx/upx/releases/download/v$VER_OLD/upx-$VER_OLD-amd64_linux.tar.xz | tar -Jx upx-$VER_OLD-amd64_linux/upx
|
||||
sudo cp upx-$VER_OLD-amd64_linux/upx /usr/local/bin/upx_old
|
||||
curl -Lo - https://github.com/upx/upx/releases/download/v$VER_NEW/upx-$VER_NEW-amd64_linux.tar.xz | tar -Jx upx-$VER_NEW-amd64_linux/upx
|
||||
sudo cp upx-$VER_NEW-amd64_linux/upx /usr/local/bin/upx_new
|
||||
rm -r upx-$VER_OLD-amd64_linux/upx upx-$VER_NEW-amd64_linux/upx
|
||||
|
||||
- name: Prepare binaries
|
||||
shell: bash
|
||||
run: |
|
||||
cd ${{ steps.bins.outputs.download-path }}
|
||||
run_upx() {
|
||||
upx --best --lzma $@ || true
|
||||
run_upx_old() {
|
||||
upx_old --best --lzma $@ || true
|
||||
}
|
||||
run_upx_new() {
|
||||
upx_new --best --lzma $@ || true
|
||||
}
|
||||
run_dir() {
|
||||
for f in $dir/* ; do
|
||||
@@ -503,8 +519,10 @@ jobs:
|
||||
case $f in
|
||||
*.tar.xz )
|
||||
tar -C $dir -xvf $f && rm $f
|
||||
if [[ $dir =~ linux ]] && [[ $dir != *-linux-mips64 ]] && [[ $dir != *-linux-lexra ]]; then
|
||||
run_upx $dir/*
|
||||
if [[ $dir = *-linux-riscv64 ]]; then
|
||||
run_upx_new $dir/*
|
||||
elif [[ $dir =~ linux ]] && [[ $dir != *-linux-mips64 ]] && [[ $dir != *-linux-lexra ]]; then
|
||||
run_upx_old $dir/*
|
||||
fi
|
||||
;;
|
||||
*.zip )
|
||||
@@ -532,6 +550,7 @@ jobs:
|
||||
*-linux-mipselsf ) run_dir linux-mipsel ;;
|
||||
*-linux-mipssf ) run_dir linux-mips ;;
|
||||
*-linux-ppc ) run_dir linux-ppc ;;
|
||||
*-linux-riscv64 ) run_dir linux-riscv64 ;;
|
||||
*-linux-x86 ) run_dir linux-x86 ;;
|
||||
*-linux-x86_64 ) run_dir linux-x86_64 ;;
|
||||
*-linux-lexra ) run_dir linux-lexra ;;
|
||||
@@ -546,15 +565,16 @@ jobs:
|
||||
run: |
|
||||
rm -rf ${{ env.repo_dir }}/.git*
|
||||
find ${{ env.repo_dir }}/binaries -type f -exec sha256sum {} \; >sha256sum.txt
|
||||
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}.tar.gz ${{ env.repo_dir }}
|
||||
zip -qr ${{ env.repo_dir }}.zip ${{ env.repo_dir }}
|
||||
tar --owner=0 --group=0 -c ${{ env.repo_dir }} | pigz -11 >${{ env.repo_dir }}.tar.gz
|
||||
zip -9qr ${{ env.repo_dir }}.zip ${{ env.repo_dir }}
|
||||
(
|
||||
cd ${{ env.repo_dir }}
|
||||
rm -rf binaries/{android*,freebsd*,win*} \
|
||||
init.d/{openrc,pfsense,runit,s6,systemd,windivert.filter.examples} \
|
||||
nfq2 ip2net mdig docs Makefile
|
||||
pigz -11 lua/*.lua
|
||||
)
|
||||
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }}
|
||||
tar --owner=0 --group=0 -c ${{ env.repo_dir }} | pigz -11 >${{ env.repo_dir }}-openwrt-embedded.tar.gz
|
||||
|
||||
- name: Upload release assets
|
||||
uses: softprops/action-gh-release@v2
|
||||
|
||||
2
binaries/readme.txt
Normal file
2
binaries/readme.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
Бинари только в релизах. Собираем с исходников или качаем релиз с гитхаба ! Инфа по сборке в docs/compile.
|
||||
Binaries are only in releases. Build from source or download release from github ! See docs/compile.
|
||||
@@ -2,9 +2,11 @@
|
||||
Скопируйте эту директорию под другим именем в blockcheck2.d, отредактируйте list файлы, впишите туда свои стратегии.
|
||||
В диалоге blockcheck2.sh выберите тест с названием вашей директории.
|
||||
Можно комментировать строки символом '#' в начале строки.
|
||||
Параметры со спец символами типа "<" должны быть эскейпнуты по правилам shell.
|
||||
Альтернативный путь до файлов стратегий можно задать переменными LIST_HTTP, LIST_HTTPS_TLS12, LIST_HTTPS_TLS13, LIST_QUIC.
|
||||
|
||||
This is simple strategy tester from a file.
|
||||
Copy this folder, write your strategies into list files and select your test in blockcheck2 dialog.
|
||||
Lines can be commented using the '#' symbol at the line start.
|
||||
Parameters with special symbols like "<" must be escaped.
|
||||
Strategy list files paths can be overriden in env variables : LIST_HTTP, LIST_HTTPS_TLS12, LIST_HTTPS_TLS13, LIST_QUIC.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# write nfqws2 parameters here
|
||||
# WARNING : parameters with special symbols like "<" must be escaped or will cause error
|
||||
--payload=http_req --lua-desync=http_hostcase
|
||||
--payload=http_req --lua-desync=http_methodeol
|
||||
--payload=http_req --lua-desync=fake:blob=fake_default_http:tcp_ts=-1000
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# write nfqws2 parameters here
|
||||
# WARNING : parameters with special symbols like "<" must be escaped or will cause error
|
||||
--payload tls_client_hello --lua-desync=fake:blob=fake_default_tls:tcp_ts=-1000
|
||||
--payload=tls_client_hello --lua-desync=fake:blob=0x00000000:tcp_md5:repeats=1 --lua-desync=fake:blob=fake_default_tls:tcp_md5:tls_mod=rnd,dupsid:repeats=1 --lua-desync=multisplit:pos=2
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# write nfqws2 parameters here
|
||||
# WARNING : parameters with special symbols like "<" must be escaped or will cause error
|
||||
--payload tls_client_hello --lua-desync=fake:blob=fake_default_tls:tcp_ts=-1000
|
||||
--payload tls_client_hello --lua-desync=tcpseg:pos=0,-1:seqovl=1 --lua-desync=drop
|
||||
--payload tls_client_hello --lua-desync=luaexec:code="desync.pat=tls_mod(fake_default_tls,'rnd,rndsni,dupsid,padencap',desync.reasm_data)" --lua-desync=tcpseg:pos=0,-1:seqovl=#pat:seqovl_pattern=pat --lua-desync=drop
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# write nfqws2 parameters here
|
||||
# WARNING : parameters with special symbols like "<" must be escaped or will cause error
|
||||
--payload quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=11
|
||||
--payload quic_initial --lua-desync=send:ipfrag --lua-desync=drop
|
||||
|
||||
@@ -6,7 +6,7 @@ pktws_check_http()
|
||||
|
||||
[ "$NOTEST_BASIC_HTTP" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
for s in 'http_hostcase' 'http_hostcase:spell=hoSt' 'http_domcase' 'http_methodeol'; do
|
||||
pktws_curl_test_update $1 $2 --payload http_req --lua-desync=$s
|
||||
for s in 'http_hostcase' 'http_hostcase:spell=hoSt' 'http_domcase' 'http_methodeol' 'http_unixeol'; do
|
||||
pktws_curl_test_update $1 $2 --payload=http_req --lua-desync=$s
|
||||
done
|
||||
}
|
||||
|
||||
@@ -5,7 +5,9 @@ pktws_check_http()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
local PAYLOAD="--payload http_req" repeats ok
|
||||
local PAYLOAD="--payload=http_req" repeats ok
|
||||
|
||||
[ "$NOTEST_MISC_HTTP" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
for repeats in 1 20 100 260; do
|
||||
# send starting bytes of original payload
|
||||
@@ -20,7 +22,9 @@ pktws_check_https_tls12()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
local PAYLOAD="--payload tls_client_hello" repeats ok
|
||||
local PAYLOAD="--payload=tls_client_hello" repeats ok
|
||||
|
||||
[ "$NOTEST_MISC_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
for repeats in 1 20 100 260; do
|
||||
# send starting bytes of original payload
|
||||
|
||||
39
blockcheck2.d/standard/17-oob.sh
Normal file
39
blockcheck2.d/standard/17-oob.sh
Normal file
@@ -0,0 +1,39 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
pktws_oob()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
local urp
|
||||
for urp in b 0 2 midsld; do
|
||||
pktws_curl_test_update "$1" "$2" --in-range=-s1 --lua-desync=oob:urp=$urp
|
||||
done
|
||||
}
|
||||
|
||||
pktws_check_http()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_OOB_HTTP" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_oob "$@"
|
||||
}
|
||||
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_OOB_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_oob "$@"
|
||||
}
|
||||
|
||||
pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
pktws_check_https_tls12 "$1" "$2"
|
||||
}
|
||||
@@ -1,18 +1,22 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
pktws_simple_split_tests()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain/uri
|
||||
# $3 - splits
|
||||
# $4 - PRE args for nfqws2
|
||||
local pos ok ok_any pre="$4"
|
||||
local pos ok ok_any pre="$4" func
|
||||
local splitf splitfs="multisplit multidisorder"
|
||||
|
||||
ok_any=0
|
||||
for splitf in multisplit multidisorder; do
|
||||
for splitf in $splitfs; do
|
||||
func=$splitf
|
||||
[ "$func" = multidisorder ] && func=$MULTIDISORDER
|
||||
eval need_$splitf=0
|
||||
ok=0
|
||||
for pos in $3; do
|
||||
pktws_curl_test_update $1 $2 $pre $PAYLOAD --lua-desync=$splitf:pos=$pos && ok=1
|
||||
pktws_curl_test_update $1 $2 $pre $PAYLOAD --lua-desync=$func:pos=$pos && ok=1
|
||||
done
|
||||
[ "$ok" = 1 -a "$SCANLEVEL" != force ] || eval need_$splitf=1
|
||||
[ "$ok" = 1 ] && ok_any=1
|
||||
@@ -26,7 +30,7 @@ pktws_check_http()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
local splits_http='method+2 midsld method+2,midsld'
|
||||
local PAYLOAD="--payload http_req"
|
||||
local PAYLOAD="--payload=http_req"
|
||||
|
||||
[ "$NOTEST_MULTI_HTTP" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
@@ -38,10 +42,8 @@ pktws_check_https_tls()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
||||
local PAYLOAD="--payload tls_client_hello"
|
||||
|
||||
[ "$NOTEST_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
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"
|
||||
|
||||
pktws_simple_split_tests "$1" "$2" "$splits_tls" "$3"
|
||||
}
|
||||
@@ -50,6 +52,9 @@ pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
|
||||
# do not use 'need' values obtained with wssize
|
||||
@@ -62,5 +67,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
pktws_check_http()
|
||||
{
|
||||
# $1 - test function
|
||||
@@ -5,7 +7,7 @@ pktws_check_http()
|
||||
|
||||
[ "$NOTEST_SEQOVL_HTTP" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
local PAYLOAD="--payload http_req"
|
||||
local PAYLOAD="--payload=http_req"
|
||||
|
||||
local ok pat= split f f2
|
||||
|
||||
@@ -24,8 +26,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
|
||||
}
|
||||
|
||||
@@ -34,54 +36,47 @@ pktws_seqovl_tests_tls()
|
||||
# $1 - test function
|
||||
# $2 - domain/uri
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
local ok ok_any
|
||||
local testf=$1 domain="$2" pre="$3"
|
||||
local pat rnd_mod padencap_mod split f f2
|
||||
local PAYLOAD="--payload tls_client_hello"
|
||||
local PAYLOAD="--payload=tls_client_hello"
|
||||
|
||||
pat=${SEQOVL_PATTERN_HTTPS:+seqovl_pat}
|
||||
pat=${pat:-fake_default_tls}
|
||||
rnd_mod="--lua-init=$pat=tls_mod($pat,'rnd')"
|
||||
padencap_mod="--lua-desync=luaexec:code=desync.pat=tls_mod($pat,'rnd,dupsid,padencap',desync.reasm_data)"
|
||||
padencap_mod="--lua-desync=luaexec:code=desync.patmod=tls_mod($pat,'rnd,dupsid,padencap',desync.reasm_data)"
|
||||
|
||||
ok=0
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=tcpseg:pos=0,-1:seqovl=1 --lua-desync=drop && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$rnd_mod $pre $PAYLOAD --lua-desync=tcpseg:pos=0,-1:seqovl=#$pat:seqovl_pattern=$pat --lua-desync=drop && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$pre $PAYLOAD $padencap_mod --lua-desync=tcpseg:pos=0,-1:seqovl=#pat:seqovl_pattern=pat --lua-desync=drop && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$pre $PAYLOAD $padencap_mod --lua-desync=tcpseg:pos=0,-1:seqovl=#patmod:seqovl_pattern=patmod --lua-desync=drop && ok=1
|
||||
ok_any=$ok
|
||||
|
||||
ok=0
|
||||
for split in 10 10,sniext+1 10,sniext+4 10,midsld; do
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=multisplit:pos=$split:seqovl=1 && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$rnd_mod $pre $PAYLOAD --lua-desync=multisplit:pos=$split:seqovl=#$pat:seqovl_pattern=$pat && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$pre $PAYLOAD $padencap_mod --lua-desync=multisplit:pos=$split:seqovl=#pat:seqovl_pattern=pat && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$pre $PAYLOAD $padencap_mod --lua-desync=multisplit:pos=$split:seqovl=#patmod:seqovl_pattern=patmod && ok=1
|
||||
[ "$ok" = 1 -a "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
for split in '1 2' 'sniext sniext+1' 'sniext+3 sniext+4' 'midsld-1 midsld' '1 2,midsld'; do
|
||||
f="$(extract_arg 1 $split)"
|
||||
f2="$(extract_arg 2 $split)"
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=multidisorder:pos=$f2:seqovl=$f && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$rnd_mod $pre $PAYLOAD --lua-desync=multidisorder:pos=$f2:seqovl=$f:seqovl_pattern=$pat && ok=1
|
||||
pktws_curl_test_update $1 $2 $pre $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 ]
|
||||
}
|
||||
|
||||
pktws_check_https_tls()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
[ "$NOTEST_SEQOVL_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_seqovl_tests_tls "$1" "$2" "$3"
|
||||
}
|
||||
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_SEQOVL_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_seqovl_tests_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
pktws_seqovl_tests_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
}
|
||||
@@ -90,5 +85,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_SEQOVL_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_seqovl_tests_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -5,11 +5,13 @@ pktws_check_http()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
local PAYLOAD="--payload http_req" split
|
||||
local PAYLOAD="--payload=http_req" split
|
||||
|
||||
for split in '' multisplit multidisorder; do
|
||||
[ "$NOTEST_SYNDATA_HTTP" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
for split in '' multisplit $MULTIDISORDER; do
|
||||
pktws_curl_test_update "$1" "$2" --lua-desync=syndata ${split:+$PAYLOAD --lua-desync=$split}
|
||||
pktws_curl_test_update "$1" "$2" --lua-desync=syndata:blob=fake_default_http $PAYLOAD ${split:+$PAYLOAD --lua-desync=$split}
|
||||
pktws_curl_test_update "$1" "$2" --lua-desync=syndata:blob=fake_default_http ${split:+$PAYLOAD --lua-desync=$split}
|
||||
done
|
||||
}
|
||||
|
||||
@@ -19,9 +21,9 @@ pktws_check_https_tls()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
local PAYLOAD="--payload tls_client_hello" ok=0 pre="$3" split
|
||||
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
|
||||
@@ -36,6 +38,8 @@ pktws_check_https_tls12()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_SYNDATA_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
}
|
||||
@@ -45,5 +49,7 @@ pktws_check_https_tls13()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_SYNDATA_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ pktws_check_http()
|
||||
|
||||
need_fake=0
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
ok_any=0
|
||||
ok=0
|
||||
@@ -40,7 +40,7 @@ pktws_check_http()
|
||||
for ff in $fake 0x00000000; do
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=fake_http:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS && ok=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --payload empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --payload=empty "--out-range=<s1" --lua-desync=send:$TCP_MD5 && ok=1
|
||||
done
|
||||
done
|
||||
for ttl in $attls; do
|
||||
@@ -55,8 +55,8 @@ pktws_check_http()
|
||||
done
|
||||
|
||||
[ $ok = 0 -a "$SCANLEVEL" != force ] && need_fake=1
|
||||
[ $ok = 1 ] && okany=1
|
||||
[ $okany = 1 ]
|
||||
[ $ok = 1 ] && ok_any=1
|
||||
[ $ok_any = 1 ]
|
||||
}
|
||||
|
||||
pktws_fake_https_vary_()
|
||||
@@ -76,7 +76,7 @@ pktws_fake_https_vary()
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "$5" && ok_any=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && \
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:tcp_md5" && ok_any=1
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:$TCP_MD5" && ok_any=1
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
@@ -86,8 +86,6 @@ pktws_check_https_tls()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
[ "$NOTEST_FAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
local testf=$1 domain="$2" pre="$3"
|
||||
local ok ok_any ttls attls f fake fooling
|
||||
local PAYLOAD="--payload=tls_client_hello"
|
||||
@@ -102,8 +100,8 @@ pktws_check_https_tls()
|
||||
|
||||
need_fake=0
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
ok_any=0
|
||||
ok=0
|
||||
@@ -125,14 +123,17 @@ pktws_check_https_tls()
|
||||
done
|
||||
|
||||
[ $ok = 0 -a "$SCANLEVEL" != force ] && need_fake=1
|
||||
[ $ok = 1 ] && okany=1
|
||||
[ $okany = 1 ]
|
||||
[ $ok = 1 ] && ok_any=1
|
||||
[ $ok_any = 1 ]
|
||||
}
|
||||
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
|
||||
# do not use 'need' values obtained with wssize
|
||||
@@ -145,5 +146,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@ pktws_check_faked()
|
||||
local PAYLOAD="--payload=$3"
|
||||
local FAKED_PATTERN="$5"
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
# do not test fakedsplit if multisplit works
|
||||
[ "$need_multisplit" = 0 -a "$SCANLEVEL" != force ] || splitfs=fakedsplit
|
||||
@@ -42,7 +42,7 @@ pktws_check_faked()
|
||||
for split in $splits; do
|
||||
pktws_curl_test_update $testf $domain ${FAKED_PATTERN:+--blob=faked_pat:@"$FAKED_PATTERN" }$pre $PAYLOAD --lua-desync=$splitf:${FAKED_PATTERN:+pattern=faked_pat:}pos=$split:$fooling && ok=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKED_PATTERN:+--blob=faked_pat:@"$FAKED_PATTERN" }$pre $PAYLOAD --lua-desync=$splitf:${FAKED_PATTERN:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS --payload empty --out-range="<s1" --lua-desync=send:tcp_md5 && ok=1
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKED_PATTERN:+--blob=faked_pat:@"$FAKED_PATTERN" }$pre $PAYLOAD --lua-desync=$splitf:${FAKED_PATTERN:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS --payload=empty --out-range="<s1" --lua-desync=send:$TCP_MD5 && ok=1
|
||||
done
|
||||
done
|
||||
for ttl in $attls; do
|
||||
@@ -77,7 +77,6 @@ pktws_check_https_tls()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
[ "$NOTEST_FAKED_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
local splits='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
||||
pktws_check_faked $1 "$2" tls_client_hello "$splits" "$FAKED_PATTERN_HTTPS" "$3"
|
||||
@@ -87,6 +86,9 @@ pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKED_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
|
||||
# do not use 'need' values obtained with wssize
|
||||
@@ -99,5 +101,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKED_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
|
||||
pktws_hostfake_vary_()
|
||||
{
|
||||
local ok_any=0 testf=$1 domain="$2" fooling="$3" pre="$4" post="$5" disorder
|
||||
@@ -22,7 +21,7 @@ pktws_hostfake_vary()
|
||||
pktws_hostfake_vary_ "$1" "$2" "$3" "$4" "$5" && ok_any=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && \
|
||||
pktws_hostfake_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:tcp_md5" && ok_any=1
|
||||
pktws_hostfake_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:$TCP_MD5" && ok_any=1
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
@@ -37,8 +36,8 @@ pktws_check_hostfake()
|
||||
local ok ttls attls f fooling
|
||||
local PAYLOAD="--payload=$3"
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
need_hostfakesplit=0
|
||||
ok=0
|
||||
@@ -58,7 +57,7 @@ pktws_check_hostfake()
|
||||
pktws_hostfake_vary $testf $domain "ip${IPVV}_autottl=-$ttl,3-20" "$pre" "$f" && [ "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
done
|
||||
[ $ok = 0 -a "$SCANLEVEL" != force ] && eval need_hostfake=1
|
||||
[ $ok = 0 -a "$SCANLEVEL" != force ] && need_hostfakesplit=1
|
||||
[ $ok = 1 ]
|
||||
}
|
||||
|
||||
@@ -77,14 +76,15 @@ pktws_check_https_tls()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
[ "$NOTEST_HOSTFAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_hostfake $1 "$2" tls_client_hello "$3"
|
||||
}
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_HOSTFAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
|
||||
# do not use 'need' values obtained with wssize
|
||||
@@ -97,5 +97,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_HOSTFAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -16,13 +16,13 @@ pktws_check_http()
|
||||
fake=fake_default_http
|
||||
fi
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
# do not test fake + multisplit if multisplit works
|
||||
[ "$need_multisplit" = 0 -a "$SCANLEVEL" != force ] || splitfs=multisplit
|
||||
# do not test fake + multidisorder if multidisorder works
|
||||
[ "$need_multidisorder" = 0 -a "$SCANLEVEL" != force ] || splitfs="${splitfs:+$splitfs }multidisorder"
|
||||
[ "$need_multidisorder" = 0 -a "$SCANLEVEL" != force ] || splitfs="${splitfs:+$splitfs }$MULTIDISORDER"
|
||||
|
||||
for splitf in $splitfs; do
|
||||
ok=0
|
||||
@@ -46,7 +46,7 @@ pktws_check_http()
|
||||
for ff in $fake 0x00000000; do
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split && ok=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=fake_http:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split --payload empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=fake_http:@"$FAKE_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split --payload=empty "--out-range=<s1" --lua-desync=send:$TCP_MD5 && ok=1
|
||||
done
|
||||
done
|
||||
done
|
||||
@@ -71,7 +71,7 @@ pktws_fake_https_vary_()
|
||||
shift; shift; shift
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=multisplit:blob=$fake:$fooling:pos=2:nodrop:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid,padencap:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
[ "$ok_any" = 1 ] && ok=1
|
||||
@@ -82,7 +82,7 @@ pktws_fake_https_vary()
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "$5" && ok_any=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && \
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:tcp_md5" && ok_any=1
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:$TCP_MD5" && ok_any=1
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
@@ -92,10 +92,8 @@ pktws_check_https_tls()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
[ "$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
|
||||
@@ -106,13 +104,13 @@ pktws_check_https_tls()
|
||||
fake=fake_default_tls
|
||||
fi
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
# 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
|
||||
@@ -148,6 +146,9 @@ pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
}
|
||||
@@ -156,5 +157,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ pktws_check_http()
|
||||
fake=fake_default_http
|
||||
fi
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
# do not test fake + multisplit if multisplit works
|
||||
[ "$need_fakedsplit" = 0 -a "$SCANLEVEL" != force ] || splitfs=fakedsplit
|
||||
@@ -46,7 +46,7 @@ pktws_check_http()
|
||||
for ff in $fake 0x00000000; do
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }${FAKED_PATTERN_HTTP:+--blob=faked_pat:@"$FAKED_PATTERN_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTP:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS && ok=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }${FAKED_PATTERN_HTTP:+--blob=faked_pat:@"$FAKED_PATTERN_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTP:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS --payload empty "--out-range=<s1" --lua-desync=send:tcp_md5 && ok=1
|
||||
contains "$fooling" tcp_md5 && pktws_curl_test_update $testf $domain ${FAKE_HTTP:+--blob=$fake:@"$FAKE_HTTP" }${FAKED_PATTERN_HTTP:+--blob=faked_pat:@"$FAKED_PATTERN_HTTP" }$PAYLOAD --lua-desync=fake:blob=$ff:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTP:+pattern=faked_pat:}pos=$split:$fooling:repeats=$FAKE_REPEATS --payload=empty "--out-range=<s1" --lua-desync=send:$TCP_MD5 && ok=1
|
||||
done
|
||||
done
|
||||
done
|
||||
@@ -69,11 +69,11 @@ pktws_fake_https_vary_()
|
||||
{
|
||||
local ok_any=0 testf=$1 domain="$2" fooling="$3" pre="$4" post="$5"
|
||||
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=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
|
||||
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 ${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
|
||||
|
||||
}
|
||||
@@ -83,7 +83,7 @@ pktws_fake_https_vary()
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "$5" && ok_any=1
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && \
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:tcp_md5" && ok_any=1
|
||||
pktws_fake_https_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:$TCP_MD5" && ok_any=1
|
||||
[ "$ok_any" = 1 ]
|
||||
}
|
||||
|
||||
@@ -93,8 +93,6 @@ pktws_check_https_tls()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
[ "$NOTEST_FAKE_FAKED_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 PAYLOAD="--payload=tls_client_hello"
|
||||
@@ -107,8 +105,8 @@ pktws_check_https_tls()
|
||||
fake=fake_default_tls
|
||||
fi
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
# do not test fake + fakedsplit if fakedsplit works
|
||||
[ "$need_fakedsplit" = 0 -a "$SCANLEVEL" != force ] || splitfs=fakedsplit
|
||||
@@ -149,6 +147,9 @@ pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_FAKED_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
}
|
||||
@@ -157,5 +158,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_FAKED_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ pktws_hostfake_vary()
|
||||
pktws_hostfake_vary_ "$1" "$2" "$3" "$4" "$5"
|
||||
# duplicate SYN with MD5
|
||||
contains "$fooling" tcp_md5 && \
|
||||
pktws_hostfake_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:tcp_md5"
|
||||
pktws_hostfake_vary_ "$1" "$2" "$3" "$4" "${5:+$5 }--payload=empty --out-range=<s1 --lua-desync=send:$TCP_MD5"
|
||||
}
|
||||
|
||||
pktws_check_hostfake()
|
||||
@@ -29,12 +29,12 @@ 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
|
||||
|
||||
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
[ "$MAX_TTL" = 0 ] || ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
|
||||
[ "$MAX_AUTOTTL_DELTA" = 0 ] || attls=$(seq -s ' ' $MIN_AUTOTTL_DELTA $MAX_AUTOTTL_DELTA)
|
||||
|
||||
ok=0
|
||||
for ttl in $ttls; do
|
||||
@@ -69,7 +69,7 @@ pktws_check_http()
|
||||
local FAKE="$FAKE_HTTP"
|
||||
|
||||
if [ -n "$FAKE_HTTP" ]; then
|
||||
fake=bfake
|
||||
fake=fake_http
|
||||
else
|
||||
fake=fake_default_http
|
||||
fi
|
||||
@@ -83,13 +83,11 @@ pktws_check_https_tls()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
[ "$NOTEST_FAKE_HOSTFAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
local PAYLOAD="--payload=tls_client_hello"
|
||||
local FAKE="$FAKE_HTTPS"
|
||||
|
||||
if [ -n "$FAKE_HTTPS" ]; then
|
||||
fake=bfake
|
||||
fake=fake_tls
|
||||
else
|
||||
fake=fake_default_tls
|
||||
fi
|
||||
@@ -101,6 +99,9 @@ pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_HOSTFAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
}
|
||||
@@ -109,5 +110,8 @@ pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
[ "$NOTEST_FAKE_HOSTFAKE_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
pktws_check_http3()
|
||||
{
|
||||
# $1 - test function
|
||||
@@ -5,8 +7,8 @@ pktws_check_http3()
|
||||
|
||||
[ "$NOTEST_QUIC" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
local repeats fake pos
|
||||
local PAYLOAD="--payload quic_initial"
|
||||
local repeats fake pos fool
|
||||
local PAYLOAD="--payload=quic_initial"
|
||||
|
||||
if [ -n "$FAKE_QUIC" ]; then
|
||||
fake=fake_quic
|
||||
@@ -18,6 +20,12 @@ pktws_check_http3()
|
||||
pktws_curl_test_update $1 $2 ${FAKE_QUIC:+--blob=$fake:@"$FAKE_QUIC" }$PAYLOAD --lua-desync=fake:blob=$fake:repeats=$repeats && [ "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
|
||||
[ "$IPV" = 6 ] && {
|
||||
for fool in ip6_hopbyhop ip6_destopt ip6_hopbyhop:ip6_destopt; do
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=send:$fool --lua-desync=drop
|
||||
done
|
||||
}
|
||||
|
||||
for pos in 8 16 32 64; do
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=send:ipfrag:ipfrag_pos_udp=$pos --lua-desync=drop && [ "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
|
||||
@@ -2,6 +2,20 @@ 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}
|
||||
|
||||
TCP_MD5=tcp_md5
|
||||
# OpenBSD can occupy 24 bytes in tcp options in SYN packet leaving no space for the md5 header
|
||||
[ "$UNAME" = OpenBSD ] && TCP_MD5=$TCP_MD5:tcp_nop_del
|
||||
|
||||
131
blockcheck2.sh
131
blockcheck2.sh
@@ -26,7 +26,6 @@ CURL=${CURL:-curl}
|
||||
|
||||
TEST_DEFAULT=${TEST_DEFAULT:-standard}
|
||||
DOMAINS_DEFAULT=${DOMAINS_DEFAULT:-rutracker.org}
|
||||
QNUM=${QNUM:-59781}
|
||||
SOCKS_PORT=${SOCKS_PORT:-1993}
|
||||
WS_UID=${WS_UID:-1}
|
||||
WS_GID=${WS_GID:-3003}
|
||||
@@ -35,26 +34,28 @@ DVTWS2=${DVTWS2:-${ZAPRET_BASE}/nfq2/dvtws2}
|
||||
WINWS2=${WINWS2:-${ZAPRET_BASE}/nfq2/winws2}
|
||||
MDIG=${MDIG:-${ZAPRET_BASE}/mdig/mdig}
|
||||
DESYNC_MARK=0x10000000
|
||||
IPFW_RULE_NUM=${IPFW_RULE_NUM:-1}
|
||||
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}
|
||||
QUIC_PORT=${QUIC_PORT:-443}
|
||||
UNBLOCKED_DOM=${UNBLOCKED_DOM:-iana.org}
|
||||
PARALLEL_OUT=/tmp/zapret_parallel
|
||||
SIM_SUCCESS_RATE=${SIM_SUCCESS_RATE:-10}
|
||||
|
||||
HDRTEMP=/tmp/zapret-hdr
|
||||
IPFW_RULE_MAX=${IPFW_RULE_MAX:-999}
|
||||
IPFW_RULE_NUM=${IPFW_RULE_NUM:-$(($$ % $IPFW_RULE_MAX + 1))}
|
||||
IPFW_DIVERT_PORT=${IPFW_DIVERT_PORT:-$(($$ % 64536 + 1000))}
|
||||
QNUM=${QNUM:-$(($$ % 64536 + 1000))}
|
||||
|
||||
NFT_TABLE=blockcheck
|
||||
IPSET_FILE=/tmp/blockcheck_ipset_$$.txt
|
||||
PARALLEL_OUT=/tmp/zapret_parallel_$$
|
||||
HDRTEMP=/tmp/zapret-hdr-$$
|
||||
NFT_TABLE=blockcheck$$
|
||||
IPT_OUT_CHAIN=blockcheck_output_$$
|
||||
IPT_IN_CHAIN=blockcheck_input_$$
|
||||
IPT_COMMENT="-m comment --comment blockcheck_$$"
|
||||
|
||||
DNSCHECK_DNS=${DNSCHECK_DNS:-8.8.8.8 1.1.1.1 77.88.8.1}
|
||||
DNSCHECK_DOM=${DNSCHECK_DOM:-pornhub.com ej.ru rutracker.org www.torproject.org bbc.com}
|
||||
@@ -63,7 +64,6 @@ DNSCHECK_DIG1=/tmp/dig1.txt
|
||||
DNSCHECK_DIG2=/tmp/dig2.txt
|
||||
DNSCHECK_DIGS=/tmp/digs.txt
|
||||
|
||||
IPSET_FILE=/tmp/blockcheck_ipset.txt
|
||||
|
||||
unset PF_STATUS
|
||||
PF_RULES_SAVE=/tmp/pf-zapret-save.conf
|
||||
@@ -244,7 +244,7 @@ mdig_vars()
|
||||
# $1 - ip version 4/6
|
||||
# $2 - hostname
|
||||
|
||||
hostvar=$(echo $2 | sed -e 's/[\./?&#@%*$^:~=!()+-]/_/g')
|
||||
hostvar=$(echo $2 | sed -e 's/[\./?&#@%*$^:~=!()+-]/_/g' | tr 'A-Z' 'a-z')
|
||||
cachevar=DNSCACHE_${hostvar}_$1
|
||||
countvar=${cachevar}_COUNT
|
||||
eval count=\$${countvar}
|
||||
@@ -301,7 +301,7 @@ mdig_resolve_all()
|
||||
mdig_vars "$1" "$sdom"
|
||||
if [ -n "$count" ]; then
|
||||
n=0
|
||||
while [ "$n" -le $count ]; do
|
||||
while [ "$n" -lt $count ]; do
|
||||
eval ip__=\$${cachevar}_$n
|
||||
if [ -n "$ips__" ]; then
|
||||
ips__="$ips__ $ip__"
|
||||
@@ -412,8 +412,14 @@ zp_already_running()
|
||||
CYGWIN)
|
||||
win_process_exists $PKTWSD || win_process_exists winws || win_process_exists goodbyedpi
|
||||
;;
|
||||
*)
|
||||
FreeBSD|OpenBSD)
|
||||
process_exists $PKTWSD || process_exists tpws || process_exists dvtws
|
||||
;;
|
||||
Linux)
|
||||
process_exists $PKTWSD || process_exists tpws || process_exists nfqws
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
esac
|
||||
}
|
||||
check_already()
|
||||
@@ -637,11 +643,11 @@ curl_with_dig()
|
||||
# $2 - domain name
|
||||
# $3 - port
|
||||
# $4+ - curl params
|
||||
local dom=$2 port=$3
|
||||
local dom="$2" port=$3
|
||||
local sdom suri ip
|
||||
|
||||
split_by_separator "$dom" / sdom suri
|
||||
mdig_resolve $1 ip $sdom
|
||||
mdig_resolve $1 ip "$sdom"
|
||||
shift ; shift ; shift
|
||||
if [ -n "$ip" ]; then
|
||||
curl_with_subst_ip "$sdom" "$port" "$ip" "$@"
|
||||
@@ -656,12 +662,12 @@ curl_probe()
|
||||
# $3 - port
|
||||
# $4 - subst ip
|
||||
# $5+ - curl params
|
||||
local ipv=$1 dom=$2 port=$3 subst=$4
|
||||
local ipv=$1 dom="$2" port=$3 subst=$4
|
||||
shift; shift; shift; shift
|
||||
if [ -n "$subst" ]; then
|
||||
curl_with_subst_ip $dom $port $subst "$@"
|
||||
curl_with_subst_ip "$dom" $port $subst "$@"
|
||||
else
|
||||
curl_with_dig $ipv $dom $port "$@"
|
||||
curl_with_dig $ipv "$dom" $port "$@"
|
||||
fi
|
||||
}
|
||||
curl_test_http()
|
||||
@@ -672,7 +678,7 @@ curl_test_http()
|
||||
# $4 - "detail" - detail info
|
||||
|
||||
local code loc hdrt="${HDRTEMP}_${!:-$$}.txt" dom="$(tolower "$2")"
|
||||
curl_probe $1 $2 $HTTP_PORT "$3" -SsD "$hdrt" -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT "http://$2" -o /dev/null 2>&1 || {
|
||||
curl_probe $1 "$2" $HTTP_PORT "$3" -SsD "$hdrt" -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT "http://$2" -o /dev/null 2>&1 || {
|
||||
code=$?
|
||||
rm -f "$hdrt"
|
||||
return $code
|
||||
@@ -684,6 +690,7 @@ curl_test_http()
|
||||
code=$(hdrfile_http_code "$hdrt")
|
||||
[ "$code" = 301 -o "$code" = 302 -o "$code" = 307 -o "$code" = 308 ] && {
|
||||
loc=$(hdrfile_location "$hdrt")
|
||||
split_by_separator "$dom" / dom
|
||||
tolower "$loc" | grep -qE "^https?://.*$dom(/|$)" ||
|
||||
tolower "$loc" | grep -vqE '^https?://' || {
|
||||
echo suspicious redirection $code to : $loc
|
||||
@@ -707,7 +714,7 @@ curl_test_https_tls12()
|
||||
# $3 - subst ip
|
||||
|
||||
# do not use tls 1.3 to make sure server certificate is not encrypted
|
||||
curl_probe $1 $2 $HTTPS_PORT "$3" $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.2 $TLSMAX12 "https://$2" -o /dev/null 2>&1
|
||||
curl_probe $1 "$2" $HTTPS_PORT "$3" $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.2 $TLSMAX12 "https://$2" -o /dev/null 2>&1
|
||||
}
|
||||
curl_test_https_tls13()
|
||||
{
|
||||
@@ -716,7 +723,7 @@ curl_test_https_tls13()
|
||||
# $3 - subst ip
|
||||
|
||||
# force TLS1.3 mode
|
||||
curl_probe $1 $2 $HTTPS_PORT "$3" $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.3 $TLSMAX13 "https://$2" -o /dev/null 2>&1
|
||||
curl_probe $1 "$2" $HTTPS_PORT "$3" $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.3 $TLSMAX13 "https://$2" -o /dev/null 2>&1
|
||||
}
|
||||
|
||||
curl_test_http3()
|
||||
@@ -725,7 +732,7 @@ curl_test_http3()
|
||||
# $2 - domain name
|
||||
|
||||
# force QUIC only mode without tcp
|
||||
curl_with_dig $1 $2 $QUIC_PORT $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME_QUIC --http3-only $CURL_OPT "https://$2" -o /dev/null 2>&1
|
||||
curl_with_dig $1 "$2" $QUIC_PORT $HTTPS_HEAD -Ss -A "$USER_AGENT" --max-time $CURL_MAX_TIME_QUIC --http3-only $CURL_OPT "https://$2" -o /dev/null 2>&1
|
||||
}
|
||||
|
||||
ipt_aux_scheme()
|
||||
@@ -735,24 +742,24 @@ ipt_aux_scheme()
|
||||
# $3 - port
|
||||
|
||||
# to avoid possible INVALID state drop
|
||||
[ "$2" = tcp ] && IPT_ADD_DEL $1 INPUT -p $2 --sport $3 ! --syn -j ACCEPT
|
||||
[ "$2" = tcp ] && IPT_ADD_DEL $1 INPUT -p $2 --sport $3 ! --syn $IPT_COMMENT -j ACCEPT
|
||||
|
||||
local icmp_filter="-p icmp -m icmp --icmp-type"
|
||||
[ "$IPV" = 6 ] && icmp_filter="-p icmpv6 -m icmp6 --icmpv6-type"
|
||||
IPT_ADD_DEL $1 INPUT $icmp_filter time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
|
||||
IPT_ADD_DEL $1 INPUT $icmp_filter time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK $IPT_COMMENT -j DROP
|
||||
|
||||
# for strategies with incoming packets involved (autottl)
|
||||
IPT_ADD_DEL $1 OUTPUT -p $2 --dport $3 -m conntrack --ctstate INVALID -j ACCEPT
|
||||
IPT_ADD_DEL $1 OUTPUT -p $2 --dport $3 -m conntrack --ctstate INVALID $IPT_COMMENT -j ACCEPT
|
||||
if [ "$IPV" = 6 -a -n "$IP6_DEFRAG_DISABLE" ]; then
|
||||
# the only way to reliable disable ipv6 defrag. works only in 4.16+ kernels
|
||||
IPT_ADD_DEL $1 OUTPUT -t raw -p $2 -m frag -j CT --notrack
|
||||
IPT_ADD_DEL $1 OUTPUT -t raw -p $2 -m frag $IPT_COMMENT -j CT --notrack
|
||||
elif [ "$IPV" = 4 ]; then
|
||||
# enable fragments
|
||||
IPT_ADD_DEL $1 OUTPUT -f -j ACCEPT
|
||||
IPT_ADD_DEL $1 OUTPUT -f $IPT_COMMENT -j ACCEPT
|
||||
fi
|
||||
# enable everything generated by nfqws (works only in OUTPUT, not in FORWARD)
|
||||
# raw table may not be present
|
||||
IPT_ADD_DEL $1 OUTPUT -t raw -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j CT --notrack
|
||||
IPT_ADD_DEL $1 OUTPUT -t raw -m mark --mark $DESYNC_MARK/$DESYNC_MARK $IPT_COMMENT -j CT --notrack
|
||||
}
|
||||
ipt_scheme()
|
||||
{
|
||||
@@ -762,18 +769,18 @@ ipt_scheme()
|
||||
|
||||
local ip
|
||||
|
||||
$IPTABLES -t mangle -N blockcheck_output 2>/dev/null
|
||||
$IPTABLES -t mangle -F blockcheck_output
|
||||
IPT OUTPUT -t mangle -j blockcheck_output
|
||||
$IPTABLES -t mangle -N $IPT_OUT_CHAIN 2>/dev/null
|
||||
$IPTABLES -t mangle -F $IPT_OUT_CHAIN
|
||||
IPT OUTPUT -t mangle -j $IPT_OUT_CHAIN
|
||||
|
||||
# prevent loop
|
||||
$IPTABLES -t mangle -A blockcheck_output -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j RETURN
|
||||
$IPTABLES -t mangle -A blockcheck_output ! -p $1 -j RETURN
|
||||
$IPTABLES -t mangle -A blockcheck_output -p $1 ! --dport $2 -j RETURN
|
||||
$IPTABLES -t mangle -A $IPT_OUT_CHAIN -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j RETURN
|
||||
$IPTABLES -t mangle -A $IPT_OUT_CHAIN ! -p $1 -j RETURN
|
||||
$IPTABLES -t mangle -A $IPT_OUT_CHAIN -p $1 ! --dport $2 -j RETURN
|
||||
|
||||
for ip in $3; do
|
||||
$IPTABLES -t mangle -A blockcheck_output -d $ip -j CONNMARK --or-mark $DESYNC_MARK
|
||||
$IPTABLES -t mangle -A blockcheck_output -d $ip -j NFQUEUE --queue-num $QNUM
|
||||
$IPTABLES -t mangle -A $IPT_OUT_CHAIN -d $ip -j CONNMARK --or-mark $DESYNC_MARK
|
||||
$IPTABLES -t mangle -A $IPT_OUT_CHAIN -d $ip -j NFQUEUE --queue-num $QNUM
|
||||
done
|
||||
|
||||
ipt_aux_scheme 1 $1 $2
|
||||
@@ -849,9 +856,9 @@ pktws_ipt_unprepare()
|
||||
case "$FWTYPE" in
|
||||
iptables)
|
||||
ipt_aux_scheme 0 $1 $2
|
||||
IPT_DEL OUTPUT -t mangle -j blockcheck_output
|
||||
$IPTABLES -t mangle -F blockcheck_output 2>/dev/null
|
||||
$IPTABLES -t mangle -X blockcheck_output 2>/dev/null
|
||||
IPT_DEL OUTPUT -t mangle -j $IPT_OUT_CHAIN
|
||||
$IPTABLES -t mangle -F $IPT_OUT_CHAIN 2>/dev/null
|
||||
$IPTABLES -t mangle -X $IPT_OUT_CHAIN 2>/dev/null
|
||||
;;
|
||||
nftables)
|
||||
nft delete table inet $NFT_TABLE 2>/dev/null
|
||||
@@ -879,17 +886,17 @@ pktws_ipt_prepare_tcp()
|
||||
|
||||
pktws_ipt_prepare tcp $1 "$2"
|
||||
|
||||
# for autottl mode
|
||||
# for autottl mode and tcp_mss detection
|
||||
case "$FWTYPE" in
|
||||
iptables)
|
||||
$IPTABLES -N blockcheck_input -t mangle 2>/dev/null
|
||||
$IPTABLES -F blockcheck_input -t mangle 2>/dev/null
|
||||
IPT INPUT -t mangle -j blockcheck_input
|
||||
$IPTABLES -t mangle -A blockcheck_input ! -p tcp -j RETURN
|
||||
$IPTABLES -t mangle -A blockcheck_input -p tcp ! --sport $1 -j RETURN
|
||||
$IPTABLES -t mangle -A blockcheck_input -p tcp ! --tcp-flags SYN,ACK SYN,ACK -j RETURN
|
||||
$IPTABLES -N $IPT_IN_CHAIN -t mangle 2>/dev/null
|
||||
$IPTABLES -F $IPT_IN_CHAIN -t mangle 2>/dev/null
|
||||
IPT INPUT -t mangle -j $IPT_IN_CHAIN
|
||||
$IPTABLES -t mangle -A $IPT_IN_CHAIN ! -p tcp -j RETURN
|
||||
$IPTABLES -t mangle -A $IPT_IN_CHAIN -p tcp ! --sport $1 -j RETURN
|
||||
$IPTABLES -t mangle -A $IPT_IN_CHAIN -p tcp ! --tcp-flags SYN,ACK SYN,ACK -j RETURN
|
||||
for ip in $2; do
|
||||
$IPTABLES -A blockcheck_input -t mangle -s $ip -j NFQUEUE --queue-num $QNUM
|
||||
$IPTABLES -A $IPT_IN_CHAIN -t mangle -s $ip -j NFQUEUE --queue-num $QNUM
|
||||
done
|
||||
;;
|
||||
nftables)
|
||||
@@ -913,9 +920,9 @@ pktws_ipt_unprepare_tcp()
|
||||
|
||||
case "$FWTYPE" in
|
||||
iptables)
|
||||
IPT_DEL INPUT -t mangle -j blockcheck_input
|
||||
$IPTABLES -t mangle -F blockcheck_input 2>/dev/null
|
||||
$IPTABLES -t mangle -X blockcheck_input 2>/dev/null
|
||||
IPT_DEL INPUT -t mangle -j $IPT_IN_CHAIN
|
||||
$IPTABLES -t mangle -F $IPT_IN_CHAIN 2>/dev/null
|
||||
$IPTABLES -t mangle -X $IPT_IN_CHAIN 2>/dev/null
|
||||
;;
|
||||
esac
|
||||
}
|
||||
@@ -943,7 +950,9 @@ pktws_start()
|
||||
"$DVTWS2" --port=$IPFW_DIVERT_PORT --lua-init=@"$ZAPRET_BASE/lua/zapret-lib.lua" --lua-init=@"$ZAPRET_BASE/lua/zapret-antidpi.lua" "$@" >/dev/null &
|
||||
;;
|
||||
CYGWIN)
|
||||
"$WINWS2" $WF --ipset="$IPSET_FILE" --lua-init=@"$ZAPRET_BASE/lua/zapret-lib.lua" --lua-init=@"$ZAPRET_BASE/lua/zapret-antidpi.lua" "$@" >/dev/null &
|
||||
# allow multiple PKTWS instances with the same wf filter but different ipset
|
||||
# some methods require empty acks
|
||||
"$WINWS2" --wf-dup-check=0 --wf-tcp-empty=1 $WF --ipset="$IPSET_FILE" --lua-init=@"$ZAPRET_BASE/lua/zapret-lib.lua" --lua-init=@"$ZAPRET_BASE/lua/zapret-antidpi.lua" "$@" >/dev/null &
|
||||
;;
|
||||
esac
|
||||
PID=$!
|
||||
@@ -994,7 +1003,7 @@ curl_test()
|
||||
if [ "$PARALLEL" = 1 ]; then
|
||||
rm -f "${PARALLEL_OUT}"*
|
||||
for n in $(seq -s ' ' 1 $REPEATS); do
|
||||
$1 "$IPV" $2 $3 "$4" >"${PARALLEL_OUT}_$n" &
|
||||
$1 "$IPV" "$2" $3 "$4" >"${PARALLEL_OUT}_$n" &
|
||||
pids="${pids:+$pids }$!"
|
||||
done
|
||||
n=1
|
||||
@@ -1013,7 +1022,7 @@ curl_test()
|
||||
while [ $n -lt $REPEATS ]; do
|
||||
n=$(($n+1))
|
||||
[ $REPEATS -gt 1 ] && printf "[attempt $n] "
|
||||
if $1 "$IPV" $2 $3 "$4" ; then
|
||||
if $1 "$IPV" "$2" $3 "$4" ; then
|
||||
[ $REPEATS -gt 1 ] && echo 'AVAILABLE'
|
||||
else
|
||||
code=$?
|
||||
@@ -1038,7 +1047,7 @@ ws_curl_test()
|
||||
# $2 - test function
|
||||
# $3 - domain
|
||||
# $4,$5,$6, ... - ws params
|
||||
local code ws_start=$1 testf=$2 dom=$3
|
||||
local code ws_start=$1 testf=$2 dom="$3"
|
||||
|
||||
[ "$SIMULATE" = 1 ] && {
|
||||
n=$(random 0 99)
|
||||
@@ -1054,7 +1063,7 @@ ws_curl_test()
|
||||
shift
|
||||
shift
|
||||
$ws_start "$@"
|
||||
curl_test $testf $dom
|
||||
curl_test $testf "$dom"
|
||||
code=$?
|
||||
ws_kill
|
||||
return $code
|
||||
@@ -1064,11 +1073,11 @@ pktws_curl_test()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
# $3,$4,$5, ... - nfqws/dvtws params
|
||||
local testf=$1 dom=$2 strategy code
|
||||
local testf=$1 dom="$2" strategy code
|
||||
|
||||
shift; shift;
|
||||
echo - $testf ipv$IPV $dom : $PKTWSD ${WF:+$WF }${PKTWS_EXTRA_PRE:+$PKTWS_EXTRA_PRE }${PKTWS_EXTRA_PRE_1:+"$PKTWS_EXTRA_PRE_1" }${PKTWS_EXTRA_PRE_2:+"$PKTWS_EXTRA_PRE_2" }${PKTWS_EXTRA_PRE_3:+"$PKTWS_EXTRA_PRE_3" }${PKTWS_EXTRA_PRE_4:+"$PKTWS_EXTRA_PRE_4" }${PKTWS_EXTRA_PRE_5:+"$PKTWS_EXTRA_PRE_5" }${PKTWS_EXTRA_PRE_6:+"$PKTWS_EXTRA_PRE_6" }${PKTWS_EXTRA_PRE_7:+"$PKTWS_EXTRA_PRE_7" }${PKTWS_EXTRA_PRE_8:+"$PKTWS_EXTRA_PRE_8" }${PKTWS_EXTRA_PRE_9:+"$PKTWS_EXTRA_PRE_9" }$@${PKTWS_EXTRA_POST:+ $PKTWS_EXTRA_POST}${PKTWS_EXTRA_POST_1:+ "$PKTWS_EXTRA_POST_1"}${PKTWS_EXTRA_POST_2:+ "$PKTWS_EXTRA_POST_2"}${PKTWS_EXTRA_POST_3:+ "$PKTWS_EXTRA_POST_3"}${PKTWS_EXTRA_POST_4:+ "$PKTWS_EXTRA_POST_4"}${PKTWS_EXTRA_POST_5:+ "$PKTWS_EXTRA_POST_5"}${PKTWS_EXTRA_POST_6:+ "$PKTWS_EXTRA_POST_6"}${PKTWS_EXTRA_POST_7:+ "$PKTWS_EXTRA_POST_7"}${PKTWS_EXTRA_POST_8:+ "$PKTWS_EXTRA_POST_8"}${PKTWS_EXTRA_POST_9:+ "$PKTWS_EXTRA_POST_9"}
|
||||
ws_curl_test pktws_start $testf $dom ${PKTWS_EXTRA_PRE:+$PKTWS_EXTRA_PRE }${PKTWS_EXTRA_PRE_1:+"$PKTWS_EXTRA_PRE_1" }${PKTWS_EXTRA_PRE_2:+"$PKTWS_EXTRA_PRE_2" }${PKTWS_EXTRA_PRE_3:+"$PKTWS_EXTRA_PRE_3" }${PKTWS_EXTRA_PRE_4:+"$PKTWS_EXTRA_PRE_4" }${PKTWS_EXTRA_PRE_5:+"$PKTWS_EXTRA_PRE_5" }${PKTWS_EXTRA_PRE_6:+"$PKTWS_EXTRA_PRE_6" }${PKTWS_EXTRA_PRE_7:+"$PKTWS_EXTRA_PRE_7" }${PKTWS_EXTRA_PRE_8:+"$PKTWS_EXTRA_PRE_8" }${PKTWS_EXTRA_PRE_9:+"$PKTWS_EXTRA_PRE_9" }"$@"${PKTWS_EXTRA_POST:+ $PKTWS_EXTRA_POST}${PKTWS_EXTRA_POST_1:+ "$PKTWS_EXTRA_POST_1"}${PKTWS_EXTRA_POST_2:+ "$PKTWS_EXTRA_POST_2"}${PKTWS_EXTRA_POST_3:+ "$PKTWS_EXTRA_POST_3"}${PKTWS_EXTRA_POST_4:+ "$PKTWS_EXTRA_POST_4"}${PKTWS_EXTRA_POST_5:+ "$PKTWS_EXTRA_POST_5"}${PKTWS_EXTRA_POST_6:+ "$PKTWS_EXTRA_POST_6"}${PKTWS_EXTRA_POST_7:+ "$PKTWS_EXTRA_POST_7"}${PKTWS_EXTRA_POST_8:+ "$PKTWS_EXTRA_POST_8"}${PKTWS_EXTRA_POST_9:+ "$PKTWS_EXTRA_POST_9"}
|
||||
ws_curl_test pktws_start $testf "$dom" ${PKTWS_EXTRA_PRE:+$PKTWS_EXTRA_PRE }${PKTWS_EXTRA_PRE_1:+"$PKTWS_EXTRA_PRE_1" }${PKTWS_EXTRA_PRE_2:+"$PKTWS_EXTRA_PRE_2" }${PKTWS_EXTRA_PRE_3:+"$PKTWS_EXTRA_PRE_3" }${PKTWS_EXTRA_PRE_4:+"$PKTWS_EXTRA_PRE_4" }${PKTWS_EXTRA_PRE_5:+"$PKTWS_EXTRA_PRE_5" }${PKTWS_EXTRA_PRE_6:+"$PKTWS_EXTRA_PRE_6" }${PKTWS_EXTRA_PRE_7:+"$PKTWS_EXTRA_PRE_7" }${PKTWS_EXTRA_PRE_8:+"$PKTWS_EXTRA_PRE_8" }${PKTWS_EXTRA_PRE_9:+"$PKTWS_EXTRA_PRE_9" }"$@"${PKTWS_EXTRA_POST:+ $PKTWS_EXTRA_POST}${PKTWS_EXTRA_POST_1:+ "$PKTWS_EXTRA_POST_1"}${PKTWS_EXTRA_POST_2:+ "$PKTWS_EXTRA_POST_2"}${PKTWS_EXTRA_POST_3:+ "$PKTWS_EXTRA_POST_3"}${PKTWS_EXTRA_POST_4:+ "$PKTWS_EXTRA_POST_4"}${PKTWS_EXTRA_POST_5:+ "$PKTWS_EXTRA_POST_5"}${PKTWS_EXTRA_POST_6:+ "$PKTWS_EXTRA_POST_6"}${PKTWS_EXTRA_POST_7:+ "$PKTWS_EXTRA_POST_7"}${PKTWS_EXTRA_POST_8:+ "$PKTWS_EXTRA_POST_8"}${PKTWS_EXTRA_POST_9:+ "$PKTWS_EXTRA_POST_9"}
|
||||
|
||||
code=$?
|
||||
[ "$code" = 0 ] && {
|
||||
@@ -1090,11 +1099,11 @@ xxxws_curl_test_update()
|
||||
# $2 - test function
|
||||
# $3 - domain
|
||||
# $4,$5,$6, ... - nfqws2/dvtws2 params
|
||||
local code xxxf=$1 testf=$2 dom=$3
|
||||
local code xxxf=$1 testf=$2 dom="$3"
|
||||
shift
|
||||
shift
|
||||
shift
|
||||
$xxxf $testf $dom "$@"
|
||||
$xxxf $testf "$dom" "$@"
|
||||
code=$?
|
||||
[ $code = 0 ] && strategy="${strategy:-$@}"
|
||||
return $code
|
||||
@@ -1318,7 +1327,6 @@ check_domain_http_tcp()
|
||||
local ips
|
||||
|
||||
# in case was interrupted before
|
||||
pktws_ipt_unprepare_tcp $2
|
||||
ws_kill
|
||||
|
||||
check_domain_prolog $1 $2 $4 || return
|
||||
@@ -1346,7 +1354,6 @@ check_domain_http_udp()
|
||||
local ips
|
||||
|
||||
# in case was interrupted before
|
||||
pktws_ipt_unprepare_udp $2
|
||||
ws_kill
|
||||
|
||||
check_domain_prolog $1 $2 $3 || return
|
||||
|
||||
@@ -95,7 +95,7 @@ end_with_newline()
|
||||
}
|
||||
trim()
|
||||
{
|
||||
awk '{gsub(/^ +| +$/,"")}1'
|
||||
awk '{gsub(/^[ \t]+|[ \t]+$/,"")}1'
|
||||
}
|
||||
split_by_separator()
|
||||
{
|
||||
@@ -119,7 +119,7 @@ dir_is_not_empty()
|
||||
# $1 - directory
|
||||
local n
|
||||
[ -d "$1" ] || return 1
|
||||
n=$(ls "$1" | wc -c | xargs)
|
||||
n=$(ls -A "$1" | wc -c | xargs)
|
||||
[ "$n" != 0 ]
|
||||
}
|
||||
|
||||
@@ -172,15 +172,23 @@ unique()
|
||||
|
||||
is_linked_to_busybox()
|
||||
{
|
||||
local IFS F P
|
||||
|
||||
local IFS F P BB
|
||||
|
||||
BB="$(which busybox)"
|
||||
|
||||
IFS=:
|
||||
for path in $PATH; do
|
||||
F=$path/$1
|
||||
P="$(readlink $F)"
|
||||
if [ -z "$P" ] && [ -x $F ] && [ ! -L $F ]; then return 1; fi
|
||||
[ "${P%busybox*}" != "$P" ] && return
|
||||
F="$path/$1"
|
||||
if [ -L "$F" ]; then
|
||||
P="$(readlink $F)"
|
||||
if [ -z "$P" ] && [ -x $F ] && [ ! -L $F ]; then return 1; fi
|
||||
[ "${P%busybox*}" != "$P" ] && return
|
||||
elif [ -f "$F" -a -n "$BB" ]; then
|
||||
# possible hardlink
|
||||
[ $(get_dir_inode "$F") = $(get_dir_inode "$BB") ] && return
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
get_dir_inode()
|
||||
{
|
||||
@@ -335,7 +343,7 @@ setup_md5()
|
||||
{
|
||||
[ -n "$MD5" ] && return
|
||||
MD5=md5sum
|
||||
exists $MD5 || MD5=md5
|
||||
exists $MD5 || MD5="md5 -q"
|
||||
}
|
||||
|
||||
md5f()
|
||||
@@ -358,7 +366,7 @@ random()
|
||||
local r rs
|
||||
setup_random
|
||||
if [ -c /dev/urandom ]; then
|
||||
read rs </dev/urandom
|
||||
rs=$(dd if=/dev/urandom count=1 bs=16 2>/dev/null | hexdump -e '1 "%02x"')
|
||||
else
|
||||
rs="$RANDOM$RANDOM$(date)"
|
||||
fi
|
||||
@@ -386,9 +394,9 @@ shell_name()
|
||||
process_exists()
|
||||
{
|
||||
if exists pgrep; then
|
||||
pgrep ^$1$ >/dev/null
|
||||
pgrep "^$1$" >/dev/null
|
||||
elif exists pidof; then
|
||||
pidof $1 >/dev/null
|
||||
pidof "$1" >/dev/null
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
@@ -418,14 +426,6 @@ alloc_num()
|
||||
eval $1="$v"
|
||||
}
|
||||
|
||||
std_ports()
|
||||
{
|
||||
NFQWS2_PORTS_TCP_IPT=$(replace_char - : $NFQWS2_PORTS_TCP)
|
||||
NFQWS2_PORTS_TCP_KEEPALIVE_IPT=$(replace_char - : $NFQWS2_PORTS_TCP_KEEPALIVE)
|
||||
NFQWS2_PORTS_UDP_IPT=$(replace_char - : $NFQWS2_PORTS_UDP)
|
||||
NFQWS2_PORTS_UDP_KEEPALIVE_IPT=$(replace_char - : $NFQWS2_PORTS_UDP_KEEPALIVE)
|
||||
}
|
||||
|
||||
has_bad_ws_options()
|
||||
{
|
||||
# $1 - nfqws2 opts
|
||||
|
||||
@@ -36,9 +36,8 @@ ask_list()
|
||||
# $3 - (optional) default value
|
||||
local M_DEFAULT
|
||||
eval M_DEFAULT="\$$1"
|
||||
local M_ALL=$M_DEFAULT
|
||||
local M=""
|
||||
local m
|
||||
local M_DEFAULT_VAR="$M_DEFAULT"
|
||||
local M="" m
|
||||
|
||||
[ -n "$3" ] && { find_str_in_list "$M_DEFAULT" "$2" || M_DEFAULT="$3" ;}
|
||||
|
||||
@@ -54,5 +53,5 @@ ask_list()
|
||||
echo selected : $M
|
||||
eval $1="\"$M\""
|
||||
|
||||
[ "$M" != "$M_OLD" ]
|
||||
[ "$M" != "$M_DEFAULT_VAR" ]
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ check_system()
|
||||
|
||||
get_free_space_mb()
|
||||
{
|
||||
df -m $PWD | awk '/[0-9]%/{print $(NF-2)}'
|
||||
df -m "$1" | awk '/[0-9]%/{print $(NF-2)}'
|
||||
}
|
||||
get_ram_kb()
|
||||
{
|
||||
@@ -522,11 +522,6 @@ install_openwrt_firewall()
|
||||
{
|
||||
echo \* installing firewall script $1
|
||||
|
||||
[ -n "MODE" ] || {
|
||||
echo should specify MODE in $ZAPRET_CONFIG
|
||||
exitp 7
|
||||
}
|
||||
|
||||
echo "linking : $FW_SCRIPT_SRC => $OPENWRT_FW_INCLUDE"
|
||||
ln -fs "$FW_SCRIPT_SRC" "$OPENWRT_FW_INCLUDE"
|
||||
|
||||
@@ -784,7 +779,9 @@ select_fwtype()
|
||||
echo WARNING ! if you need large lists it may be necessary to fall back to iptables+ipset firewall
|
||||
}
|
||||
echo select firewall type :
|
||||
ask_list FWTYPE "iptables nftables" "$FWTYPE" && write_config_var FWTYPE
|
||||
ask_list FWTYPE "iptables nftables" "$FWTYPE"
|
||||
# always write config var to prevent auto discovery every time
|
||||
write_config_var FWTYPE
|
||||
}
|
||||
|
||||
dry_run_nfqws_()
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
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"
|
||||
IPSET_PORTS_NAME=zport
|
||||
|
||||
ipt()
|
||||
{
|
||||
@@ -43,7 +41,7 @@ ipt6_add_del()
|
||||
}
|
||||
ipt6a_add_del()
|
||||
{
|
||||
on_off_function ipt6 ipt6a_del "$@"
|
||||
on_off_function ipt6a ipt6_del "$@"
|
||||
}
|
||||
|
||||
is_ipt_flow_offload_avail()
|
||||
@@ -229,6 +227,16 @@ fw_reverse_nfqws_rule()
|
||||
fw_reverse_nfqws_rule6 $1 "$3" $4
|
||||
}
|
||||
|
||||
ipt_port_ipset()
|
||||
{
|
||||
# $1 - ipset name
|
||||
# $2 - ports
|
||||
ipset -q flush $1 || {
|
||||
ipset create $1 bitmap:port range 0-65535 || return
|
||||
}
|
||||
echo "$2" | tr ',' '\n' | sed -nEe "s/^.+$/add $1 &/p" | ipset -! restore
|
||||
}
|
||||
|
||||
ipt_first_packets()
|
||||
{
|
||||
# $1 - packet count
|
||||
@@ -239,26 +247,31 @@ ipt_do_nfqws_in_out()
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - tcp,udp
|
||||
# $3 - ports
|
||||
# $4 - PKT_OUT. special value : 'keepalive'
|
||||
# $5 - PKT_IN
|
||||
local f4 f6 first_packets_only
|
||||
# $4 - PKT. special value : 'keepalive'
|
||||
# $5 - 1 - out, 0 - in
|
||||
# $6 - ipset base name
|
||||
local f f4 f6 first_packets_only ipset
|
||||
[ -n "$3" ] || return
|
||||
ipset="${6}_$2"
|
||||
[ "$4" = keepalive ] && ipset="${ipset}_k"
|
||||
[ "$1" = 1 ] && ipt_port_ipset $ipset "$3"
|
||||
[ -n "$4" -a "$4" != 0 ] &&
|
||||
{
|
||||
first_packets_only="$(ipt_first_packets $4)"
|
||||
f4="-p $2 -m multiport --dports $3 $first_packets_only"
|
||||
f4="-p $2 -m set --match-set $ipset"
|
||||
if [ "$5" = 1 ]; then
|
||||
f4="$f4 dst"
|
||||
f=fw_nfqws_post
|
||||
else
|
||||
f4="$f4 src"
|
||||
f=fw_reverse_nfqws_rule
|
||||
fi
|
||||
f4="$f4 $first_packets_only"
|
||||
f6=$f4
|
||||
filter_apply_ipset_target f4 f6
|
||||
fw_nfqws_post $1 "$f4" "$f6" $QNUM
|
||||
}
|
||||
[ -n "$5" -a "$5" != 0 ] &&
|
||||
{
|
||||
first_packets_only="$(ipt_first_packets $5)"
|
||||
f4="-p $2 -m multiport --dports $3 $first_packets_only"
|
||||
f6=$f4
|
||||
filter_apply_ipset_target f4 f6
|
||||
fw_reverse_nfqws_rule $1 "$f4" "$f6" $QNUM
|
||||
$f $1 "$f4" "$f6" $QNUM
|
||||
}
|
||||
[ "$1" = 1 ] || ipset -q destroy $ipset
|
||||
}
|
||||
|
||||
zapret_do_firewall_standard_nfqws_rules_ipt()
|
||||
@@ -266,10 +279,12 @@ zapret_do_firewall_standard_nfqws_rules_ipt()
|
||||
# $1 - 1 - add, 0 - del
|
||||
|
||||
[ "$NFQWS2_ENABLE" = 1 ] && {
|
||||
ipt_do_nfqws_in_out $1 tcp "$NFQWS2_PORTS_TCP_IPT" "$NFQWS2_TCP_PKT_OUT" "$NFQWS2_TCP_PKT_IN"
|
||||
ipt_do_nfqws_in_out $1 tcp "$NFQWS2_PORTS_TCP_KEEPALIVE_IPT" keepalive "$NFQWS2_TCP_PKT_IN"
|
||||
ipt_do_nfqws_in_out $1 udp "$NFQWS2_PORTS_UDP_IPT" "$NFQWS2_UDP_PKT_OUT" "$NFQWS2_UDP_PKT_IN"
|
||||
ipt_do_nfqws_in_out $1 udp "$NFQWS2_PORTS_UDP_KEEPALIVE_IPT" keepalive "$NFQWS2_UDP_PKT_IN"
|
||||
ipt_do_nfqws_in_out $1 tcp "$NFQWS2_PORTS_TCP" "$NFQWS2_TCP_PKT_OUT" 1 $IPSET_PORTS_NAME
|
||||
ipt_do_nfqws_in_out $1 tcp "$NFQWS2_PORTS_TCP" "$NFQWS2_TCP_PKT_IN" 0 $IPSET_PORTS_NAME
|
||||
ipt_do_nfqws_in_out $1 tcp "$NFQWS2_PORTS_TCP_KEEPALIVE" keepalive 1 $IPSET_PORTS_NAME
|
||||
ipt_do_nfqws_in_out $1 udp "$NFQWS2_PORTS_UDP" "$NFQWS2_UDP_PKT_OUT" 1 $IPSET_PORTS_NAME
|
||||
ipt_do_nfqws_in_out $1 udp "$NFQWS2_PORTS_UDP" "$NFQWS2_UDP_PKT_IN" 0 $IPSET_PORTS_NAME
|
||||
ipt_do_nfqws_in_out $1 udp "$NFQWS2_PORTS_UDP_KEEPALIVE" keepalive 1 $IPSET_PORTS_NAME
|
||||
}
|
||||
}
|
||||
zapret_do_firewall_standard_rules_ipt()
|
||||
|
||||
@@ -25,7 +25,7 @@ filter_apply_hostlist_target()
|
||||
{
|
||||
# $1 - var name of nfqws params
|
||||
|
||||
local v parm parm1 parm2 parm3 parm4 parm5 parm6 parm7 parm8 parm9 parm10 parmNA
|
||||
local v parm parm1 parm2 parm3 parm4 parm5 parm6 parm7 parm8 parm9 parm10 parm11 parm12 parm13 parmNA
|
||||
eval v="\$$1"
|
||||
if contains "$v" "$HOSTLIST_MARKER" || contains "$v" "$HOSTLIST_NOAUTO_MARKER"; then
|
||||
[ "$MODE_FILTER" = hostlist -o "$MODE_FILTER" = autohostlist ] &&
|
||||
@@ -40,14 +40,15 @@ filter_apply_hostlist_target()
|
||||
parm5="${AUTOHOSTLIST_FAIL_THRESHOLD:+--hostlist-auto-fail-threshold=$AUTOHOSTLIST_FAIL_THRESHOLD}"
|
||||
parm6="${AUTOHOSTLIST_FAIL_TIME:+--hostlist-auto-fail-time=$AUTOHOSTLIST_FAIL_TIME}"
|
||||
parm7="${AUTOHOSTLIST_RETRANS_THRESHOLD:+--hostlist-auto-retrans-threshold=$AUTOHOSTLIST_RETRANS_THRESHOLD}"
|
||||
parm8="${AUTOHOSTLIST_RETRANS_MAXSEQ:+--hostlist-auto-retrans-maxseq=$AUTOHOSTLIST_RETRANS_MAXSEQ}"
|
||||
parm9="${AUTOHOSTLIST_INCOMING_MAXSEQ:+--hostlist-auto-incoming-maxseq=$AUTOHOSTLIST_INCOMING_MAXSEQ}"
|
||||
parm10="${AUTOHOSTLIST_UDP_IN:+--hostlist-auto-udp-in=$AUTOHOSTLIST_UDP_IN}"
|
||||
parm11="${AUTOHOSTLIST_UDP_OUT:+--hostlist-auto-udp-out=$AUTOHOSTLIST_UDP_OUT}"
|
||||
parm12="--hostlist=$HOSTLIST_AUTO"
|
||||
parm8="${AUTOHOSTLIST_RETRANS_RESET:+--hostlist-auto-retrans-reset=$AUTOHOSTLIST_RETRANS_RESET}"
|
||||
parm9="${AUTOHOSTLIST_RETRANS_MAXSEQ:+--hostlist-auto-retrans-maxseq=$AUTOHOSTLIST_RETRANS_MAXSEQ}"
|
||||
parm10="${AUTOHOSTLIST_INCOMING_MAXSEQ:+--hostlist-auto-incoming-maxseq=$AUTOHOSTLIST_INCOMING_MAXSEQ}"
|
||||
parm11="${AUTOHOSTLIST_UDP_IN:+--hostlist-auto-udp-in=$AUTOHOSTLIST_UDP_IN}"
|
||||
parm12="${AUTOHOSTLIST_UDP_OUT:+--hostlist-auto-udp-out=$AUTOHOSTLIST_UDP_OUT}"
|
||||
parm13="--hostlist=$HOSTLIST_AUTO"
|
||||
}
|
||||
parm="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm4:+ $parm4}${parm5:+ $parm5}${parm6:+ $parm6}${parm7:+ $parm7}${parm8:+ $parm8}${parm9:+ $parm9}${parm10:+ $parm10}${parm11:+ $parm11}"
|
||||
parmNA="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm10:+ $parm12}"
|
||||
parm="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm4:+ $parm4}${parm5:+ $parm5}${parm6:+ $parm6}${parm7:+ $parm7}${parm8:+ $parm8}${parm9:+ $parm9}${parm10:+ $parm10}${parm11:+ $parm11}${parm12:+ $parm12}"
|
||||
parmNA="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm13:+ $parm13}"
|
||||
}
|
||||
v="$(replace_str $HOSTLIST_NOAUTO_MARKER "$parmNA" "$v")"
|
||||
v="$(replace_str $HOSTLIST_MARKER "$parm" "$v")"
|
||||
|
||||
@@ -3,7 +3,6 @@ nft_connbytes="ct original packets"
|
||||
|
||||
# required for : nft -f -
|
||||
create_dev_stdin
|
||||
std_ports
|
||||
|
||||
nft_create_table()
|
||||
{
|
||||
@@ -18,6 +17,18 @@ nft_list_table()
|
||||
nft -t list table inet $ZAPRET_NFT_TABLE
|
||||
}
|
||||
|
||||
nft_add_chain()
|
||||
{
|
||||
# $1 - chain
|
||||
# $2 - params
|
||||
nft add chain inet $ZAPRET_NFT_TABLE $1 "{ $2 }"
|
||||
}
|
||||
nft_del_chain()
|
||||
{
|
||||
# $1 - chain
|
||||
nft delete chain inet $ZAPRET_NFT_TABLE $1
|
||||
}
|
||||
|
||||
nft_create_set()
|
||||
{
|
||||
# $1 - set name
|
||||
@@ -52,7 +63,7 @@ nft_flush_chain()
|
||||
nft_chain_empty()
|
||||
{
|
||||
# $1 - chain name
|
||||
local count=$(nft list chain inet $ZAPRET_NFT_TABLE prerouting | wc -l)
|
||||
local count=$(nft list chain inet $ZAPRET_NFT_TABLE $1 | wc -l)
|
||||
[ "$count" -le 4 ]
|
||||
}
|
||||
nft_rule_exists()
|
||||
@@ -65,8 +76,7 @@ nft_rule_exists()
|
||||
nft_add_rule ruletest "$2"
|
||||
rule=$(nft list chain inet $ZAPRET_NFT_TABLE ruletest | sed -n '3s/\t//gp')
|
||||
nft_flush_chain ruletest
|
||||
local yes=$(nft list chain inet $ZAPRET_NFT_TABLE $1 | sed -n "s/^[\t]*$rule\$/1/p")
|
||||
[ -n "$yes" ]
|
||||
nft list chain inet $ZAPRET_NFT_TABLE $1 | trim | grep -qxF "$rule"
|
||||
}
|
||||
|
||||
nft_del_all_chains_from_table()
|
||||
@@ -97,17 +107,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 +130,19 @@ nft_activate_chain6()
|
||||
{
|
||||
# $1 - chain name
|
||||
# $2 - saddr/daddr
|
||||
local b rule markf=
|
||||
local b rule markf= act flt_ifname
|
||||
[ "$DISABLE_IPV6" = "1" ] || {
|
||||
eval act="\$${1}_act6"
|
||||
[ -n "$act" ] && return
|
||||
|
||||
b=0
|
||||
nft_wanif6_filter_present && b=1
|
||||
flt_ifname="oifname"
|
||||
starts_with "$1" pre && flt_ifname="iifname"
|
||||
|
||||
[ "$2" = daddr ] && markf=$(nft_mark_filter)
|
||||
rule="meta mark and $DESYNC_MARK == 0 $markf"
|
||||
[ $b = 1 ] && rule="$rule oifname @wanif6"
|
||||
[ $b = 1 ] && rule="$rule $flt_ifname @wanif6"
|
||||
rule="$rule ip6 $2 != @nozapret6 jump $1"
|
||||
nft_rule_exists ${1}_hook "$rule" || nft_add_rule ${1}_hook $rule
|
||||
|
||||
@@ -159,10 +173,10 @@ cat << EOF | nft -f -
|
||||
add chain inet $ZAPRET_NFT_TABLE postnat_hook { type filter hook postrouting priority 101; }
|
||||
flush chain inet $ZAPRET_NFT_TABLE postnat_hook
|
||||
|
||||
add chain inet $ZAPRET_NFT_TABLE prerouting_hook { type filter hook prerouting priority -99; }
|
||||
flush chain inet $ZAPRET_NFT_TABLE prerouting_hook
|
||||
add chain inet $ZAPRET_NFT_TABLE prerouting
|
||||
flush chain inet $ZAPRET_NFT_TABLE prerouting
|
||||
add chain inet $ZAPRET_NFT_TABLE prerouting_hook { type filter hook prerouting priority -99; }
|
||||
flush chain inet $ZAPRET_NFT_TABLE prerouting_hook
|
||||
|
||||
add chain inet $ZAPRET_NFT_TABLE prenat_hook { type filter hook prerouting priority -101; }
|
||||
flush chain inet $ZAPRET_NFT_TABLE prenat_hook
|
||||
@@ -181,6 +195,7 @@ cat << EOF | nft -f -
|
||||
|
||||
add set inet $ZAPRET_NFT_TABLE wanif { type ifname; }
|
||||
add set inet $ZAPRET_NFT_TABLE wanif6 { type ifname; }
|
||||
add set inet $ZAPRET_NFT_TABLE lanif { type ifname; }
|
||||
|
||||
add chain inet $ZAPRET_NFT_TABLE ruletest
|
||||
flush chain inet $ZAPRET_NFT_TABLE ruletest
|
||||
@@ -226,8 +241,6 @@ cat << EOF | nft -f - 2>/dev/null
|
||||
delete chain inet $ZAPRET_NFT_TABLE flow_offload_always
|
||||
delete chain inet $ZAPRET_NFT_TABLE ruletest
|
||||
EOF
|
||||
# unfortunately this approach breaks udp desync of the connection initiating packet (new, first one)
|
||||
# delete chain inet $ZAPRET_NFT_TABLE predefrag
|
||||
}
|
||||
nft_del_flowtable()
|
||||
{
|
||||
@@ -253,14 +266,17 @@ nft_create_or_update_flowtable()
|
||||
nft_flush_ifsets()
|
||||
{
|
||||
cat << EOF | nft -f - 2>/dev/null
|
||||
flush set inet $ZAPRET_NFT_TABLE wanif
|
||||
flush set inet $ZAPRET_NFT_TABLE wanif6
|
||||
|
||||
for set in wanif wanif6 lanif; do
|
||||
flush set inet $ZAPRET_NFT_TABLE $set
|
||||
done
|
||||
EOF
|
||||
}
|
||||
nft_list_ifsets()
|
||||
{
|
||||
nft list set inet $ZAPRET_NFT_TABLE wanif
|
||||
nft list set inet $ZAPRET_NFT_TABLE wanif6
|
||||
for set in wanif wanif6 lanif; do
|
||||
nft list set inet $ZAPRET_NFT_TABLE $set
|
||||
done
|
||||
nft list flowtable inet $ZAPRET_NFT_TABLE ft 2>/dev/null
|
||||
}
|
||||
|
||||
@@ -398,7 +414,9 @@ nft_fill_ifsets()
|
||||
# calling all in one shot helps not to waste cpu time many times
|
||||
|
||||
script="flush set inet $ZAPRET_NFT_TABLE wanif
|
||||
flush set inet $ZAPRET_NFT_TABLE wanif6"
|
||||
flush set inet $ZAPRET_NFT_TABLE wanif6
|
||||
flush set inet $ZAPRET_NFT_TABLE lanif"
|
||||
nft_script_add_ifset_element lanif "$1"
|
||||
|
||||
[ "$DISABLE_IPV4" = "1" ] || nft_script_add_ifset_element wanif "$2"
|
||||
[ "$DISABLE_IPV6" = "1" ] || nft_script_add_ifset_element wanif6 "$3"
|
||||
|
||||
@@ -26,8 +26,11 @@ IPSET_OPT="hashsize 262144 maxelem $SET_MAXELEM"
|
||||
IP2NET_OPT4="--prefix-length=22-30 --v4-threshold=3/4"
|
||||
IP2NET_OPT6="--prefix-length=56-64 --v6-threshold=5"
|
||||
# options for auto hostlist
|
||||
# NOTE : in order for these adjustment to work it's required to redirect enough starting packets
|
||||
# NOTE : set PKT_IN, PKT_OUT variables appropriately
|
||||
AUTOHOSTLIST_INCOMING_MAXSEQ=4096
|
||||
AUTOHOSTLIST_RETRANS_MAXSEQ=65536
|
||||
AUTOHOSTLIST_RETRANS_MAXSEQ=32768
|
||||
AUTOHOSTLIST_RETRANS_RESET=1
|
||||
AUTOHOSTLIST_RETRANS_THRESHOLD=3
|
||||
AUTOHOSTLIST_FAIL_THRESHOLD=3
|
||||
AUTOHOSTLIST_FAIL_TIME=60
|
||||
@@ -38,6 +41,10 @@ AUTOHOSTLIST_DEBUGLOG=0
|
||||
|
||||
# number of parallel threads for domain list resolves
|
||||
MDIG_THREADS=30
|
||||
# EAI_AGAIN retries
|
||||
MDIG_EAGAIN=10
|
||||
# delay between EAI_AGAIN retries (ms)
|
||||
MDIG_EAGAIN_DELAY=500
|
||||
|
||||
# ipset/*.sh can compress large lists
|
||||
GZIP_LISTS=1
|
||||
@@ -51,7 +58,7 @@ GZIP_LISTS=1
|
||||
DESYNC_MARK=0x40000000
|
||||
DESYNC_MARK_POSTNAT=0x20000000
|
||||
|
||||
# do not pass outgoing traffic to tpws/nfqws not marked with this bit
|
||||
# do not pass outgoing traffic to nfqws not marked with this bit
|
||||
# this setting allows to write your own rules to limit traffic that should be fooled
|
||||
# for example based on source IP or incoming interface name
|
||||
# no filter if not defined
|
||||
@@ -64,11 +71,10 @@ NFQWS2_PORTS_TCP=80,443
|
||||
NFQWS2_PORTS_UDP=443
|
||||
# PKT_OUT means connbytes dir original
|
||||
# PKT_IN means connbytes dir reply
|
||||
# this is --dpi-desync-cutoff=nX kernel mode implementation for linux. it saves a lot of CPU.
|
||||
NFQWS2_TCP_PKT_OUT=$((6+$AUTOHOSTLIST_RETRANS_THRESHOLD))
|
||||
NFQWS2_TCP_PKT_IN=3
|
||||
NFQWS2_UDP_PKT_OUT=$((6+$AUTOHOSTLIST_RETRANS_THRESHOLD))
|
||||
NFQWS2_UDP_PKT_IN=0
|
||||
NFQWS2_TCP_PKT_OUT=20
|
||||
NFQWS2_TCP_PKT_IN=10
|
||||
NFQWS2_UDP_PKT_OUT=5
|
||||
NFQWS2_UDP_PKT_IN=3
|
||||
# redirect outgoing traffic without connbytes limiter and incoming with connbytes limiter
|
||||
# normally it's needed only for stateless DPI that matches every packet in a single TCP session
|
||||
# typical example are plain HTTP keep alives
|
||||
@@ -96,11 +102,12 @@ FLOWOFFLOAD=donttouch
|
||||
#OPENWRT_WAN4="wan vpn"
|
||||
#OPENWRT_WAN6="wan6 vpn6"
|
||||
|
||||
# for routers based on desktop linux and macos. has no effect in openwrt.
|
||||
# for routers based on classic linux. has no effect in openwrt.
|
||||
# CHOOSE LAN and optinally WAN/WAN6 NETWORK INTERFACES
|
||||
# or leave them commented if its not router
|
||||
# it's possible to specify multiple interfaces like this : IFACE_WAN="eth0 eth1 eth2"
|
||||
# if IFACE_WAN6 is not defined it take the value of IFACE_WAN
|
||||
#IFACE_LAN=eth0
|
||||
#IFACE_WAN=eth1
|
||||
#IFACE_WAN6="ipsec0 wireguard0 he_net"
|
||||
|
||||
|
||||
169
docs/changes.txt
169
docs/changes.txt
@@ -90,3 +90,172 @@ v0.7
|
||||
* nfqws2: push desync.track.pos.dt as float with nsec accuracy
|
||||
* zapret-auto: override host autostate key in automate_host_record
|
||||
* nfqws2: rewrite udp autohostlist failure detector logic
|
||||
|
||||
v0.7.1
|
||||
|
||||
* init.d: nft fix non-working incoming redirect
|
||||
* nfqws2: cancel reasm if server window size is smaller than expected reasm size
|
||||
* nfqws2: add EOL at the end of truncated buffered DLOG line if it's too large. increase log line buffer
|
||||
* nfqws2: autohostlist reset fail counter if udp_in > threshold
|
||||
* nfqws2: reduced default retrans maxseq to 32768
|
||||
* nfqws2: solved inability to get SSID using nl80211 on kernels 5.19+
|
||||
|
||||
v0.7.2
|
||||
|
||||
* zapret-lib: fix broken is_retransmission()
|
||||
* zapret-auto: add success detector logic
|
||||
* nfqws2: clean lua cutoff on profile change
|
||||
* zapret-auto: separate hostkey function
|
||||
|
||||
v0.7.4
|
||||
|
||||
* nfqws2, zapret-lib : check tcp sequence range overflow
|
||||
* zapret-lib: seq compare functions
|
||||
* nfqws2: add l3_len, l4_len to dissect
|
||||
* nfqws2: fix broken l7proto profile rediscovery
|
||||
* winws2: harden sandbox. disable child process execution , some UI interaction and desktop settings change
|
||||
|
||||
v0.7.5
|
||||
|
||||
* zapret-auto: orchestrator "repeater"
|
||||
* blockcheck2: check http3 with ipv6 exthdr
|
||||
* github actions: separate target arm-old with LUA classic, not JIT
|
||||
* zapret-auto: iff/neg in repeater
|
||||
* zapret-antidpi: multidisorder_legacy
|
||||
* ipset: remove get_reestr_hostlist.sh and get_reestr_resolve.sh because zapret-info does not and will probably not ever update
|
||||
* nfqws2: fix "reasm cancelled" if no incoming traffic redirected
|
||||
* blockcheck2: MULTIDISORDER=multidisorder_legacy
|
||||
|
||||
v0.7.6
|
||||
|
||||
* nfqws2: reevaluate profile on l7/host discovery in any direction
|
||||
* nfqws2: dtls protocol detection
|
||||
* nfqws2: autohostlist reset retransmitter to break long wait
|
||||
* zapret-auto: stadard_failure_detector reset retransmitter to break long wait
|
||||
* nfqws2, init.d, windivert : dht and wg detection changes
|
||||
|
||||
v0.8.0
|
||||
|
||||
* init.d: 50-dht4all NFQWS_OPT_DHT_PKT_OUT
|
||||
* nfqws2: (LUA_COMPAT_VER=4) support 48-bit arithmetics
|
||||
* github actions: remove arm-old target - luajit fail reason revealed
|
||||
* nfqws2: do not treat quic handshake messages as initials
|
||||
* zapret-lib: tls dissector/reconstructor
|
||||
* zapret-antidpi: tls_client_hello_clone
|
||||
* zapret-antidpi: "optional" arg to blob taking functions
|
||||
* nfqws2: support gzipped lua file. auto use script.lua.gz
|
||||
|
||||
v0.8.1
|
||||
|
||||
* nfqws2: fix bu48 crash and wrong results in bitset
|
||||
* zapret-lib: http_reconstruct_req
|
||||
* zapret-antidpi: http_unixeol
|
||||
* blockcheck2: http_unixeol test
|
||||
|
||||
v0.8.2
|
||||
|
||||
* nfqws2: do not start if NFQWS2_COMPAT_VER unexpected
|
||||
* nfqws2: cache dns response IP addresses if --ipcache-hostname enabled
|
||||
* winws2: remove hardcoded filter for loopback
|
||||
* init.d: ressurect @lanif in nft scheme
|
||||
* init.d: fix broken @wanif/@wanif6 fill in sysv nft scheme
|
||||
* init.d: 80-dns-intercept
|
||||
* winws2: --wf-filter-loopback
|
||||
* blockcheck2: NOTEST_MISC_HTTP[S], NOTEST_SYNDATA_HTTP[S]
|
||||
|
||||
v0.8.3
|
||||
|
||||
* nfqws2, zapret-lib: gzip compression and decompression
|
||||
* nfqws2: ignore trailing spaces and tabs in hostlists and ipsets. "host.com " or "1.2.3.4 " are ok now
|
||||
* init.d: 99-lan-filter custom script
|
||||
* mdig: --eagain, --eagain-delay
|
||||
|
||||
v0.8.4
|
||||
|
||||
* winws2: fix loopback large packets processing (up to 64K)
|
||||
* zapret-lib, zapret-antidpi: use numeric indexes in http dissects
|
||||
* nfqws2: move ctx from lightuserdata to userdata. prevents crashes on specific ARM cpus
|
||||
* nfqws2: alternative representation of payload filter in execution_plan item
|
||||
* nfqws2: --payload-disable
|
||||
* nfqws2: gracefully shutdown on SIGINT and SIGTERM
|
||||
* nfqws2: harden wireguard detection. do not detect if reserved bytes 1..3 != 0
|
||||
|
||||
v0.8.5
|
||||
|
||||
* nfqws2: do not require / in the beginning of URI in http
|
||||
* zapret-lib: rawsend_dissect_segmented support URG
|
||||
* zapret-antidpi: oob
|
||||
* blockcheck2: 17-oob.sh
|
||||
* nfqws2: set desync.tcp_mss to minimum of both ends or default if at least one is unknown
|
||||
* zapret-lib: tcp_nop_del
|
||||
* blockcheck2: tcp_nop_del in SYN packets with md5 in openbsd
|
||||
|
||||
v0.8.6
|
||||
|
||||
* winws2, blockcheck2: allow multiple instances in windows, linux, freebsd (not openbsd)
|
||||
* nfqws2: fix critical bug - wrong ipv6 dissection
|
||||
* zapret-auto: fix standard_failure_detector http redirect regression
|
||||
|
||||
v0.9.0
|
||||
|
||||
* nfqws2: removed hard check for host: presence in http_req
|
||||
* nfqws2: file open test before destroying in-memory content of ipset/hostlist
|
||||
* github actions: lua 5.5
|
||||
* nfqws2: enable dead reasm protection in wsize=0 case
|
||||
* nfqws2: --intercept
|
||||
* winws2: changed icon to multi-res png up to 256px
|
||||
* nfqws2: support icmp and ipp
|
||||
* nfqws2: VERDICT_PRESERVE_NEXT
|
||||
* nfqws2: keepsum reconstruct option
|
||||
* nfqws2: more helpers
|
||||
* zapret-obfs: ippxor, udp2icmp, synhide
|
||||
* nfqws2: LUA_COMPAT_VER=5
|
||||
* winws2: --wf-raw-filter
|
||||
* nfqws2: conntrack_feed
|
||||
* winws2: use windivert bulk mode
|
||||
* nfqws2: template free import
|
||||
|
||||
v0.9.1
|
||||
|
||||
* nfqws2: 'stat', 'clock_getfloattime' luacalls
|
||||
* nfqws2: bcryptorandom normalize behavior when system entropy is low. prevent blocks
|
||||
* nfqws2: --new[=name]
|
||||
* winws2: fix not setting signal handlers
|
||||
|
||||
v0.9.2
|
||||
|
||||
* nfqws2: bt and utp_bt protocol detectors
|
||||
* nfqws2: localtime,gmtime,timelocal,timegm luacalls
|
||||
* winws2: load wlanapi.dll dynamically only if needed
|
||||
* winws2: fixed lost windivert deinit on logical network disappear
|
||||
|
||||
v0.9.3
|
||||
|
||||
* nfqws2: handling of incoming fragmented packets (no reconstruct, raw ip payload)
|
||||
* zapret-auto: per_instance_condition orchestrator
|
||||
* zapret-auto: "instances" argument in condition orchestrator
|
||||
* zapret-auto: cond_tcp_has_ts, cond_lua iff functions
|
||||
* zapret-lib: replay_execution_plan and plan_clear max parameter
|
||||
* init.d: use bitmap:port ipset for standard dports
|
||||
* github: reduce executables files size
|
||||
* install_bin: added linux-riscv64 scan dir
|
||||
* github actions: added linux-riscv64 arch
|
||||
|
||||
v0.9.4
|
||||
|
||||
* github actions: update upx to 5.1.0. use upx for linux-riscv5
|
||||
* github actions: stronger zip and gz compression
|
||||
* nfqws2: --chdir
|
||||
* nfqws2: fixed wrong scale factor application to winsize
|
||||
* nfqws2: very old kernels compat
|
||||
|
||||
v0.9.4.2
|
||||
|
||||
* builder_linux: simple scripts to build static linux bins for any supported architecture
|
||||
* zapret-auto: incompatible change. cond_lua "code" parameter => "cond_code". to avoid collision with luaexec
|
||||
|
||||
v0.9.4.3
|
||||
|
||||
* nfqws2: fix broken wifi ssid update
|
||||
* github: revert to upx 4.2.4 for all archs except riscv64
|
||||
* zapret-lib: apply_fooling throws error if tcp_ts,tcp_seq,tcp_ack,ip_ttl,ip6_ttl,ip_autottl,ip6_autottl are empty or invalid
|
||||
|
||||
@@ -1,16 +1,39 @@
|
||||
debian,ubuntu :
|
||||
* debian,ubuntu :
|
||||
|
||||
apt install make gcc zlib1g-dev libcap-dev libnetfilter-queue-dev libmnl-dev libsystemd-dev libluajit2-5.1-dev
|
||||
make -C /opt/zapret2 systemd
|
||||
|
||||
FreeBSD :
|
||||
* linux static :
|
||||
|
||||
need any x86_64 classic linux distribution
|
||||
tested on debian/ubuntu/fedora 2020+
|
||||
if your distro is very exotic, old or not glibc based you can debootstrap a modern debian/ubuntu system and chroot to it
|
||||
NOTE: it's not possible to build luajit in chroot under standard openwrt kernel. build process requires 32-bit x86 support, kernel is compiled without it.
|
||||
NOTE: toolchains are pre-compiled for x86_64 glibc. they can't run on arm or anything that is not x86_64.
|
||||
|
||||
optionally review "common.inc" for Lua and LuaJIT versions
|
||||
|
||||
debian/ubuntu: apt install curl xz-utils bzip2 unzip make gcc gcc-multilib libc6-dev libcap-dev pkg-config
|
||||
fedora: dnf install curl xz bzip2 unzip make gcc glibc-devel glibc-devel.i686 libcap-devel pkg-config
|
||||
|
||||
copy directory "builder-linux" somethere with enough free disk space (up to 2G for all toolchains)
|
||||
run "get_toolchains.sh"
|
||||
select architectures you need or "ALL"
|
||||
run "build_deps.sh", select "ALL"
|
||||
run "build_zapret2.sh", select "ALL"
|
||||
get static musl bins from "binaries" folder
|
||||
"zapret2" is downloaded from github master branch. if you need specific version - download manually to "zapret2" dir
|
||||
i586 and riscv64 targets are built with classic PUC Lua
|
||||
|
||||
* FreeBSD :
|
||||
|
||||
pkg install pkgconf
|
||||
pkg search luajit-2
|
||||
# see what's the version available
|
||||
pkg install luajit-2.1.0.20250728
|
||||
make -C /opt/zapret2
|
||||
|
||||
OpenBSD :
|
||||
* OpenBSD :
|
||||
|
||||
pkg_add luajit gmake bsd
|
||||
gmake -C /opt/zapret2
|
||||
pkg_add luajit gmake
|
||||
gmake -C /opt/zapret2 bsd
|
||||
|
||||
@@ -11,9 +11,9 @@ setup-x86_64.exe --allow-unsupported-windows --no-verify --site http://ctm.crouc
|
||||
|
||||
4) install and compile luajit from here : https://github.com/openresty/luajit2
|
||||
|
||||
download latest releast, unpack, cd to it's directory
|
||||
download latest release, unpack, cd to it's directory
|
||||
|
||||
make BUILDMODE=static CFLAGS="-Os"
|
||||
make BUILDMODE=static CFLAGS="-Os -DLUAJIT_DISABLE_FFI -ffat-lto-objects -flto=auto -ffunction-sections -fdata-sections -fvisibility=hidden"
|
||||
make install
|
||||
|
||||
5) cd to %ZAPRET_BASE%/nfq2
|
||||
@@ -32,5 +32,5 @@ Choose version 2.2.2 for Windows 10 and 2.2.0 for Windows 7.
|
||||
8) Copy cygwin1.dll, winws2.exe, windivert.dll and windivert64.sys to one folder.
|
||||
|
||||
9) Run winws2.exe from cmd.exe running as administrator.
|
||||
winws will not run from cygwin shell with cygwin1.dll copy in it's folder.
|
||||
winws will not run without cygwin1.dll outside of cygwin shell.
|
||||
winws2 will not run from cygwin shell with cygwin1.dll copy in it's folder.
|
||||
winws2 will not run without cygwin1.dll outside of cygwin shell.
|
||||
|
||||
102
docs/compile/builder-linux/build_deps.sh
Executable file
102
docs/compile/builder-linux/build_deps.sh
Executable file
@@ -0,0 +1,102 @@
|
||||
#!/bin/bash
|
||||
|
||||
EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
|
||||
. "$EXEDIR/common.inc"
|
||||
|
||||
dl_deps()
|
||||
{
|
||||
[ -d "$DEPS" ] || mkdir -p "$DEPS"
|
||||
(
|
||||
cd "$DEPS"
|
||||
exists_dir libnfnetlink-* ||
|
||||
curl -Lo - https://www.netfilter.org/pub/libnfnetlink/libnfnetlink-1.0.2.tar.bz2 | tar -xj || exit 5
|
||||
exists_dir libmnl-* ||
|
||||
curl -Lo - https://www.netfilter.org/pub/libmnl/libmnl-1.0.5.tar.bz2 | tar -xj || exit 5
|
||||
exists_dir libnetfilter_queue-* ||
|
||||
curl -Lo - https://www.netfilter.org/pub/libnetfilter_queue/libnetfilter_queue-1.0.5.tar.bz2 | tar -xj || exit 5
|
||||
exists_dir zlib-* ||
|
||||
curl -Lo - https://zlib.net/fossils/zlib-1.3.1.tar.gz | tar -xz || exit 5
|
||||
exists_dir luajit2-* ||
|
||||
curl -Lo - https://github.com/openresty/luajit2/archive/refs/tags/v${LUAJIT_RELEASE}.tar.gz | tar -xz || exit 5
|
||||
exists_dir lua-* ||
|
||||
curl -Lo - https://www.lua.org/ftp/lua-${LUA_RELEASE}.tar.gz | tar -xz || exit 5
|
||||
)
|
||||
}
|
||||
|
||||
build_netlink()
|
||||
{
|
||||
for i in libmnl libnfnetlink libnetfilter_queue ; do
|
||||
(
|
||||
cd $i-*
|
||||
[ -f "Makefile" ] && make clean
|
||||
CFLAGS="$OPTIMIZE $MINSIZE $CFLAGS" \
|
||||
LDFLAGS="$LDMINSIZE $LDFLAGS" \
|
||||
./configure --prefix= --host=$TARGET CC=$CC LD=$LD --enable-static --disable-shared --disable-dependency-tracking
|
||||
make install -j$nproc DESTDIR=$STAGING_DIR
|
||||
)
|
||||
sed -i "s|^prefix=.*|prefix=$STAGING_DIR|g" $STAGING_DIR/lib/pkgconfig/$i.pc
|
||||
done
|
||||
}
|
||||
build_zlib()
|
||||
{
|
||||
(
|
||||
cd zlib-*
|
||||
[ -f "Makefile" ] && make clean
|
||||
CFLAGS="$OPTIMIZE $MINSIZE $CFLAGS" \
|
||||
LDFLAGS="$LDMINSIZE $LDFLAGS" \
|
||||
./configure --prefix= --static
|
||||
make install -j$nproc DESTDIR=$STAGING_DIR
|
||||
)
|
||||
}
|
||||
build_lua()
|
||||
{
|
||||
(
|
||||
cd lua-${LUA_RELEASE}
|
||||
make clean
|
||||
make CC="$CC" AR="$AR rc" CFLAGS="$OPTIMIZE $MINSIZE $CFLAGS" LDFLAGS="$LDMINSIZE $LDFLAGS" linux -j$nproc
|
||||
make install INSTALL_TOP="$STAGING_DIR" INSTALL_BIN="$STAGING_DIR/bin" INSTALL_INC="$STAGING_DIR/include/lua${LUA_VER}" INSTALL_LIB="$STAGING_DIR/lib"
|
||||
)
|
||||
}
|
||||
build_luajit()
|
||||
{
|
||||
(
|
||||
cd luajit2-*
|
||||
make clean
|
||||
make BUILDMODE=static XCFLAGS=-DLUAJIT_DISABLE_FFI HOST_CC="$HOST_CC" CROSS= CC="$CC" TARGET_AR="$AR rcus" TARGET_STRIP=$STRIP TARGET_CFLAGS="$OPTIMIZE $MINSIZE $CFLAGS" TARGET_LDFLAGS="$LDMINSIZE $LDFLAGS"
|
||||
make install PREFIX= DESTDIR="$STAGING_DIR"
|
||||
)
|
||||
}
|
||||
build_luajit_for_target()
|
||||
{
|
||||
target_has_luajit $1 && {
|
||||
case "$1" in
|
||||
*64*)
|
||||
HOST_CC="$HOSTCC"
|
||||
;;
|
||||
*)
|
||||
HOST_CC="$HOSTCC -m32"
|
||||
;;
|
||||
esac
|
||||
build_luajit
|
||||
}
|
||||
}
|
||||
|
||||
check_prog curl tar gzip bzip2 sed make cc pkg-config
|
||||
check_h_files
|
||||
dl_deps
|
||||
check_toolchains
|
||||
ask_target
|
||||
|
||||
for t in $TGT; do
|
||||
buildenv $t
|
||||
pushd "$DEPS"
|
||||
install_h_files
|
||||
build_netlink
|
||||
build_zlib
|
||||
build_lua
|
||||
build_luajit_for_target $t
|
||||
popd
|
||||
buildenv_clear
|
||||
done
|
||||
62
docs/compile/builder-linux/build_zapret1.sh
Executable file
62
docs/compile/builder-linux/build_zapret1.sh
Executable file
@@ -0,0 +1,62 @@
|
||||
#!/bin/bash
|
||||
|
||||
EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
|
||||
. "$EXEDIR/common.inc"
|
||||
|
||||
ZDIR="zapret"
|
||||
ZBASE="$EXEDIR"
|
||||
BRANCH=master
|
||||
ZURL=https://github.com/bol-van/zapret/archive/refs/heads/${BRANCH}.zip
|
||||
ZBIN="$EXEDIR/binaries"
|
||||
|
||||
dl_zapret1()
|
||||
{
|
||||
if [ -d "$ZBASE/$ZDIR" ]; then
|
||||
dir_is_not_empty "$ZBASE/$ZDIR" && {
|
||||
echo "zapret dir is not empty. if you want to redownload - delete it."
|
||||
return
|
||||
}
|
||||
rmdir "$ZBASE/$ZDIR"
|
||||
fi
|
||||
(
|
||||
cd "$ZBASE"
|
||||
curl -Lo /tmp/zapret.zip "$ZURL"
|
||||
unzip /tmp/zapret.zip
|
||||
rm /tmp/zapret.zip
|
||||
mv zapret-${BRANCH} $ZDIR
|
||||
)
|
||||
}
|
||||
|
||||
check_prog curl unzip make
|
||||
dl_zapret1
|
||||
check_toolchains
|
||||
ask_target
|
||||
|
||||
[ -d "$ZBIN" ] || mkdir -p "$ZBIN"
|
||||
|
||||
for t in $TGT; do
|
||||
buildenv $t
|
||||
|
||||
translate_target $t || {
|
||||
echo COULD NOT TRANSLATE TARGET $t TO BIN DIR
|
||||
continue
|
||||
}
|
||||
|
||||
pushd $ZBASE/$ZDIR
|
||||
|
||||
make clean
|
||||
OPTIMIZE=$OPTIMIZE \
|
||||
CFLAGS="-static-libgcc -static -I$STAGING_DIR/include $MINSIZE $CFLAGS" \
|
||||
LDFLAGS="-L$STAGING_DIR/lib $LDMINSIZE $LDFLAGS" \
|
||||
make
|
||||
|
||||
[ -d "$ZBIN/$ZBINTARGET" ] || mkdir "$ZBIN/$ZBINTARGET"
|
||||
cp -f binaries/my/* "$ZBIN/$ZBINTARGET"
|
||||
|
||||
popd
|
||||
|
||||
buildenv_clear
|
||||
done
|
||||
|
||||
73
docs/compile/builder-linux/build_zapret2.sh
Executable file
73
docs/compile/builder-linux/build_zapret2.sh
Executable file
@@ -0,0 +1,73 @@
|
||||
#!/bin/bash
|
||||
|
||||
EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
|
||||
. "$EXEDIR/common.inc"
|
||||
|
||||
ZDIR="zapret2"
|
||||
ZBASE="$EXEDIR"
|
||||
BRANCH=master
|
||||
ZURL=https://github.com/bol-van/zapret2/archive/refs/heads/${BRANCH}.zip
|
||||
ZBIN="$EXEDIR/binaries"
|
||||
|
||||
dl_zapret2()
|
||||
{
|
||||
if [ -d "$ZBASE/$ZDIR" ]; then
|
||||
dir_is_not_empty "$ZBASE/$ZDIR" && {
|
||||
echo "zapret2 dir is not empty. if you want to redownload - delete it."
|
||||
return
|
||||
}
|
||||
rmdir "$ZBASE/$ZDIR"
|
||||
fi
|
||||
(
|
||||
cd "$ZBASE"
|
||||
curl -Lo /tmp/zapret2.zip "$ZURL"
|
||||
unzip /tmp/zapret2.zip
|
||||
rm /tmp/zapret2.zip
|
||||
mv zapret2-${BRANCH} $ZDIR
|
||||
)
|
||||
}
|
||||
|
||||
check_prog curl unzip make
|
||||
dl_zapret2
|
||||
check_toolchains
|
||||
ask_target
|
||||
|
||||
[ -d "$ZBIN" ] || mkdir -p "$ZBIN"
|
||||
|
||||
for t in $TGT; do
|
||||
buildenv $t
|
||||
|
||||
translate_target $t || {
|
||||
echo COULD NOT TRANSLATE TARGET $t TO BIN DIR
|
||||
continue
|
||||
}
|
||||
|
||||
pushd $ZBASE/$ZDIR
|
||||
|
||||
LUA_JIT=0
|
||||
LCFLAGS="-I${STAGING_DIR}/include/lua${LUA_VER}"
|
||||
LLIB="-L${STAGING_DIR}/lib -llua"
|
||||
target_has_luajit $t && {
|
||||
LUA_JIT=1
|
||||
LCFLAGS="-I${STAGING_DIR}/include/luajit-${LUAJIT_VER}"
|
||||
LLIB="-L${STAGING_DIR}/lib -lluajit-${LUAJIT_LUA_VER}"
|
||||
}
|
||||
|
||||
make clean
|
||||
LUA_JIT=$LUA_JIT LUA_VER=$LUA_VER LUAJIT_LUA_VER=$LUAJIT_LUA_VER \
|
||||
OPTIMIZE=$OPTIMIZE \
|
||||
MINSIZE=$MINSIZE \
|
||||
CFLAGS="-static-libgcc -static -I$STAGING_DIR/include $CFLAGS" \
|
||||
LDFLAGS="-L$STAGING_DIR/lib $LDFLAGS" \
|
||||
make LUA_JIT=$LJIT LUA_CFLAGS="$LCFLAGS" LUA_LIB="$LLIB"
|
||||
|
||||
[ -d "$ZBIN/$ZBINTARGET" ] || mkdir "$ZBIN/$ZBINTARGET"
|
||||
cp -f binaries/my/* "$ZBIN/$ZBINTARGET"
|
||||
|
||||
popd
|
||||
|
||||
buildenv_clear
|
||||
done
|
||||
|
||||
283
docs/compile/builder-linux/common.inc
Normal file
283
docs/compile/builder-linux/common.inc
Normal file
@@ -0,0 +1,283 @@
|
||||
EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
|
||||
TOOLCHAINS="$EXEDIR/toolchain"
|
||||
DEPS="$EXEDIR/deps"
|
||||
STAGE="$EXEDIR/staging"
|
||||
OPTIMIZE=${OPTIMIZE:--Oz}
|
||||
MINSIZE="${MINSIZE:--flto=auto -ffunction-sections -fdata-sections}"
|
||||
LDMINSIZE="${LDMINSIZE:--Wl,--gc-sections -flto=auto}"
|
||||
#CFLAGS=""
|
||||
LDFLAGS="-lgcc_eh $LDFLAGS"
|
||||
HOSTCC=${HOSTCC:-cc}
|
||||
LUA_VER=${LUA_VER:-5.5}
|
||||
LUA_RELEASE=${LUA_RELEASE:-5.5.0}
|
||||
LUAJIT_VER=${LUAJIT_VER:-2.1}
|
||||
LUAJIT_RELEASE=${LUAJIT_RELEASE:-2.1-20250826}
|
||||
LUAJIT_LUA_VER=${LUAJIT_LUA_VER:-5.1}
|
||||
nproc=$(nproc)
|
||||
|
||||
TARGETS="\
|
||||
aarch64-unknown-linux-musl \
|
||||
arm-unknown-linux-musleabi \
|
||||
i586-unknown-linux-musl \
|
||||
x86_64-unknown-linux-musl \
|
||||
mips-unknown-linux-muslsf \
|
||||
mips64-unknown-linux-musl \
|
||||
mips64el-unknown-linux-musl \
|
||||
mipsel-unknown-linux-muslsf \
|
||||
powerpc-unknown-linux-musl \
|
||||
riscv64-unknown-linux-musl \
|
||||
"
|
||||
|
||||
target_has_luajit()
|
||||
{
|
||||
case "$1" in
|
||||
aarch64-unknown-linux-musl| \
|
||||
arm-unknown-linux-musleabi| \
|
||||
x86_64-unknown-linux-musl| \
|
||||
mips-unknown-linux-muslsf| \
|
||||
mips64-unknown-linux-musl| \
|
||||
mips64el-unknown-linux-musl| \
|
||||
mipsel-unknown-linux-muslsf| \
|
||||
powerpc-unknown-linux-musl) \
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
REQD_H_FILES="/usr/include/sys/capability.h /usr/include/bits/libc-header-start.h"
|
||||
REQD_QUEUE_1="/usr/include/sys/queue.h"
|
||||
REQD_QUEUE_2="/usr/include/x86_64-linux-gnu/sys/queue.h"
|
||||
check_h_files()
|
||||
{
|
||||
[ ! -f "$REQD_QUEUE_1" -a ! -f "$REQD_QUEUE_2" ] && {
|
||||
echo "could not find $REQD_QUEUE_1 or $REQD_QUEUE_2"
|
||||
help_pkg
|
||||
exit 10
|
||||
}
|
||||
check_file $REQD_H_FILES
|
||||
}
|
||||
install_h_files()
|
||||
{
|
||||
if [ -f "$REQD_QUEUE_1" ]; then
|
||||
install -Dm644 -t $STAGING_DIR/include/sys $REQD_QUEUE_1
|
||||
elif [ -f "$REQD_QUEUE_2" ]; then
|
||||
install -Dm644 -t $STAGING_DIR/include/sys $REQD_QUEUE_2
|
||||
fi
|
||||
install -Dm644 -t $STAGING_DIR/include/sys $REQD_H_FILES
|
||||
}
|
||||
|
||||
buildenv()
|
||||
{
|
||||
# $1 = arch
|
||||
|
||||
export TARGET=$1
|
||||
export CC=$TARGET-gcc
|
||||
export LD=$TARGET-ld
|
||||
export AR=$TARGET-ar
|
||||
export NM=$TARGET-nm
|
||||
export STRIP=$TARGET-strip
|
||||
export STAGING_DIR="$EXEDIR/staging/$TARGET"
|
||||
[ -d "$STAGING_DIR" ] || {
|
||||
mkdir -p "$STAGING_DIR"
|
||||
mkdir -p "$STAGING_DIR/lib/pkgconfig"
|
||||
mkdir -p "$STAGING_DIR/bin"
|
||||
mkdir -p "$STAGING_DIR/include"
|
||||
}
|
||||
export PKG_CONFIG_PATH=$STAGING_DIR/lib/pkgconfig
|
||||
OLDPATH="$PATH"
|
||||
export PATH="$PATH:$TOOLCHAINS/$TARGET/bin"
|
||||
}
|
||||
buildenv_clear()
|
||||
{
|
||||
export PATH="$OLDPATH" TARGET= CC= LD= AR= NM= STRIP= STAGING_DIR= PKG_CONFIG_PATH=
|
||||
OLDPATH=
|
||||
}
|
||||
|
||||
which()
|
||||
{
|
||||
# on some systems 'which' command is considered deprecated and not installed by default
|
||||
# 'command -v' replacement does not work exactly the same way. it outputs shell aliases if present
|
||||
# $1 - executable name
|
||||
local IFS=:
|
||||
[ "$1" != "${1#/}" ] && [ -x "$1" ] && {
|
||||
echo "$1"
|
||||
return 0
|
||||
}
|
||||
for p in $PATH; do
|
||||
[ -x "$p/$1" ] && {
|
||||
echo "$p/$1"
|
||||
return 0
|
||||
}
|
||||
done
|
||||
return 1
|
||||
}
|
||||
exists()
|
||||
{
|
||||
which "$1" >/dev/null 2>/dev/null
|
||||
}
|
||||
exists_dir()
|
||||
{
|
||||
# use $1, ignore other args
|
||||
[ -d "$1" ]
|
||||
}
|
||||
|
||||
dir_is_not_empty()
|
||||
{
|
||||
# $1 - directory
|
||||
local n
|
||||
[ -d "$1" ] || return 1
|
||||
n=$(ls -A "$1" | wc -c | xargs)
|
||||
[ "$n" != 0 ]
|
||||
}
|
||||
|
||||
find_str_in_list()
|
||||
{
|
||||
# $1 - string
|
||||
# $2 - space separated values
|
||||
local v
|
||||
[ -n "$1" ] && {
|
||||
for v in $2; do
|
||||
[ "$v" = "$1" ] && return 0
|
||||
done
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
ask_list()
|
||||
{
|
||||
# $1 - mode var
|
||||
# $2 - space separated value list
|
||||
# $3 - (optional) default value
|
||||
local M_DEFAULT
|
||||
eval M_DEFAULT="\$$1"
|
||||
local M_DEFAULT_VAR="$M_DEFAULT"
|
||||
local M="" m
|
||||
|
||||
[ -n "$3" ] && { find_str_in_list "$M_DEFAULT" "$2" || M_DEFAULT="$3" ;}
|
||||
|
||||
n=1
|
||||
for m in $2; do
|
||||
echo $n : $m
|
||||
n=$(($n+1))
|
||||
done
|
||||
printf "your choice (default : $M_DEFAULT) : "
|
||||
read m
|
||||
[ -n "$m" ] && M=$(echo $2 | cut -d ' ' -f$m 2>/dev/null)
|
||||
[ -z "$M" ] && M="$M_DEFAULT"
|
||||
echo selected : $M
|
||||
eval $1="\"$M\""
|
||||
|
||||
[ "$M" != "$M_DEFAULT_VAR" ]
|
||||
}
|
||||
|
||||
ask_target()
|
||||
{
|
||||
# $1 = 1 = ask all, otherwise ask only present toolchains
|
||||
|
||||
# already set ?
|
||||
[ -n "$TGT" ] && return
|
||||
|
||||
local d ALL_TARGETS
|
||||
[ "$1" = 1 ] || {
|
||||
if dir_is_not_empty "$TOOLCHAINS"; then
|
||||
for d in "$TOOLCHAINS"/*; do
|
||||
[ -d "$d" ] && {
|
||||
d="$(basename "$d")"
|
||||
ALL_TARGETS="$ALL_TARGETS $d"
|
||||
}
|
||||
done
|
||||
fi
|
||||
}
|
||||
[ -n "$ALL_TARGETS" ] || ALL_TARGETS="$TARGETS"
|
||||
|
||||
echo "select target :"
|
||||
ask_list TARGET "ALL $ALL_TARGETS" "ALL"
|
||||
echo
|
||||
echo selected TARGET : $TARGET
|
||||
echo
|
||||
|
||||
if [ $TARGET = ALL ]; then
|
||||
TGT="$ALL_TARGETS"
|
||||
else
|
||||
TGT="$TARGET"
|
||||
fi
|
||||
}
|
||||
|
||||
check_toolchains()
|
||||
{
|
||||
dir_is_not_empty "$TOOLCHAINS" || {
|
||||
echo DOWNLOAD TOOLCHAINS FIRST
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
help_pkg()
|
||||
{
|
||||
echo "debian/ubuntu: apt install curl xz-utils bzip2 unzip make gcc gcc-multilib libc6-dev libcap-dev pkg-config"
|
||||
echo "fedora: dnf install curl xz bzip2 unzip make gcc glibc-devel glibc-devel.i686 libcap-devel pkg-config"
|
||||
}
|
||||
|
||||
check_prog()
|
||||
{
|
||||
while [ -n "$1" ]; do
|
||||
exists $1 || {
|
||||
echo $1 is not available
|
||||
help_pkg
|
||||
exit 10
|
||||
}
|
||||
shift
|
||||
done
|
||||
}
|
||||
check_file()
|
||||
{
|
||||
while [ -n "$1" ]; do
|
||||
[ -f "$1" ] || {
|
||||
echo $1 is not available
|
||||
help_pkg
|
||||
exit 10
|
||||
}
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
translate_target()
|
||||
{
|
||||
case $1 in
|
||||
aarch64-unknown-linux-musl)
|
||||
ZBINTARGET=linux-arm64
|
||||
;;
|
||||
arm-unknown-linux-musleabi)
|
||||
ZBINTARGET=linux-arm
|
||||
;;
|
||||
x86_64-unknown-linux-musl)
|
||||
ZBINTARGET=linux-x86_64
|
||||
;;
|
||||
i586-unknown-linux-musl)
|
||||
ZBINTARGET=linux-x86
|
||||
;;
|
||||
mips-unknown-linux-muslsf)
|
||||
ZBINTARGET=linux-mips
|
||||
;;
|
||||
mipsel-unknown-linux-muslsf)
|
||||
ZBINTARGET=linux-mipsel
|
||||
;;
|
||||
mips64-unknown-linux-musl)
|
||||
ZBINTARGET=linux-mips64
|
||||
;;
|
||||
mips64el-unknown-linux-musl)
|
||||
ZBINTARGET=linux-mipsel64
|
||||
;;
|
||||
powerpc-unknown-linux-musl)
|
||||
ZBINTARGET=linux-ppc
|
||||
;;
|
||||
riscv64-unknown-linux-musl)
|
||||
ZBINTARGET=linux-riscv64
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
22
docs/compile/builder-linux/get_toolchains.sh
Executable file
22
docs/compile/builder-linux/get_toolchains.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
|
||||
. "$EXEDIR/common.inc"
|
||||
|
||||
BASEURL=https://github.com/bol-van/musl-cross/releases/download/latest
|
||||
|
||||
check_prog curl tar xz
|
||||
|
||||
[ -d "$TOOLCHAINS" ] || mkdir -p "$TOOLCHAINS"
|
||||
|
||||
ask_target 1
|
||||
|
||||
(
|
||||
cd "$TOOLCHAINS"
|
||||
for t in $TGT; do
|
||||
[ -d "$t" ] && rm -r "$t"
|
||||
curl -Lo - "${BASEURL}/${t}.tar.xz" | tar -Jx
|
||||
done
|
||||
)
|
||||
@@ -26,7 +26,7 @@ define Package/nfqws2
|
||||
CATEGORY:=Network
|
||||
TITLE:=nfqws2
|
||||
SUBMENU:=Zapret
|
||||
DEPENDS:=+libnetfilter-queue +lmnl +libcap +zlib +$(LUA_DEP)
|
||||
DEPENDS:=+libnetfilter-queue +libmnl +libcap +zlib +$(LUA_DEP)
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
|
||||
5524
docs/manual.en.md
Normal file
5524
docs/manual.en.md
Normal file
File diff suppressed because it is too large
Load Diff
5717
docs/manual.md
5717
docs/manual.md
File diff suppressed because it is too large
Load Diff
162
docs/readme.md
162
docs/readme.md
@@ -1,3 +1,7 @@
|
||||
## English
|
||||
|
||||
[Manual](manual.en.md)
|
||||
|
||||
## Зачем это нужно
|
||||
|
||||
Автономное средство противодействия DPI, которое не требует подключения каких-либо сторонних серверов. Может помочь
|
||||
@@ -8,6 +12,24 @@ VPN. Может использоваться для частичной проз
|
||||
традиционные Linux-системы, FreeBSD, OpenBSD, Windows. В некоторых случаях возможна самостоятельная прикрутка
|
||||
решения к различным прошивкам.
|
||||
|
||||
[Полный мануал](manual.md)
|
||||
|
||||
|
||||
## Поддержать разработчика. Donations
|
||||
|
||||
Если вы считаете проект полезным и желаете поддержать разработку, направляйте ваши пожертвования на следующие адреса криптокошельков :
|
||||
|
||||
If you find this project useful and wish to donate here are crypto wallets :
|
||||
|
||||
USDT ERC `0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E`
|
||||
|
||||
USDT TRC `TEzAAtn4VhndqEaAyuCM78xh5W2gCjwWEo`
|
||||
|
||||
BTC `bc1qhqew3mrvp47uk2vevt5sctp7p2x9m7m5kkchve`
|
||||
|
||||
ETH `0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E`
|
||||
|
||||
|
||||
## Чем это отличается от zapret1
|
||||
|
||||
zapret2 является дальнейшим развитием проекта zapret.
|
||||
@@ -22,12 +44,12 @@ zapret2 является дальнейшим развитием проекта
|
||||
или хотя бы область , в которой их можно искать, плюс владеющий базовыми навыками программирования.
|
||||
|
||||
*nfqws2* оставляет в себе практически тот же функционал - распознавание протоколов, реассемблинг, дешифровка, управление профилями, хостлисты, ipset-ы, базовая фильтрация.
|
||||
Но он полностью лишается возможностей самостоятельно воздействовать на трафик. Часть "дурения" переносится в скриптовой язык программирования LUA.
|
||||
Но он полностью лишается возможностей самостоятельно воздействовать на трафик. Часть "дурения" переносится в скриптовой язык программирования Lua.
|
||||
|
||||
LUA код получает от C кода структурированное представление приходящих пакетов в виде дерева (диссекты), подобного тем, что вы видите в wireshark.
|
||||
Lua код получает от C кода структурированное представление приходящих пакетов в виде дерева (диссекты), подобного тем, что вы видите в wireshark.
|
||||
Туда же приходят результаты сборки или дешифровки частей некоторых протоколов (tls, quic).
|
||||
С код предоставляет функции-хелперы, позволяющие отсылать пакеты, работать с двоичными данными, разбирать TLS, искать маркер-позции и т.д.
|
||||
Имеется библиотека хелперов, написанных на LUA, а так же готовая библиотека программ атаки на DPI (стратегий), реализующая функции *nfqws1* в расширенном варианте
|
||||
С код предоставляет функции-хелперы, позволяющие отсылать пакеты, работать с двоичными данными, разбирать TLS, искать маркер-позиции и т.д.
|
||||
Имеется библиотека хелперов, написанных на Lua, а так же готовая библиотека программ атаки на DPI (стратегий), реализующая функции *nfqws1* в расширенном варианте
|
||||
и с большей гибкостью.
|
||||
|
||||
Вы всегда сможете взять и дописать что-то свое. В этом и есть смысл, чтобы борьбой с DPI смог заняться любой, кто разбирается в пакетах.
|
||||
@@ -38,9 +60,8 @@ zapret2 - инструмент для таких энтузиастов. Но э
|
||||
|
||||
## С чего начать
|
||||
|
||||
Хотелось бы избежать "талмуда" на главной странице. Поэтому начнем со способа запуска *nfqws2* и описания способов портирования стратегий *nfqws1* - как в *nfqws2* сделать то же самое, что можно было в *nfqws1*.
|
||||
Когда вы поймете как это работает, вы можете посмотреть LUA код, находящийся "под капотом". Разобрать как он работает, попробовать написать что-то свое.
|
||||
"талмуд" обязательно будет, как он есть у любых более-менее сложных проектов. Он нужен как справочник.
|
||||
Хотелось бы избежать [талмуда](manual.md) на главной странице. Поэтому начнем со способа запуска *nfqws2* и описания способов портирования стратегий *nfqws1* - как в *nfqws2* сделать то же самое, что можно было в *nfqws1*.
|
||||
Когда вы поймете как это работает, вы можете посмотреть Lua код, находящийся "под капотом". Разобрать как он работает, попробовать написать что-то свое, руководствуясь [талмудом](manual.md) как справочником.
|
||||
|
||||
### Механика обработки трафика
|
||||
|
||||
@@ -88,11 +109,11 @@ nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-antidpi.
|
||||
--payload=tls_client_hello,http_req --lua-desync=multisplit:pos=1:seqovl=5:seqovl_pattern=0x1603030000
|
||||
```
|
||||
|
||||
Данный пример предполагает, что в той же директории находятся файлы `zapret-lib.lua` - библиотека хелперов на LUA и `zapret-antidpi.lua` - библиотека базовых стратегий.
|
||||
`--lua-init` может содержать LUA код в виде строки. Так удобно писать простой код, например присвоить константу переменной, чтобы не создавать файлы ради этой мелочи.
|
||||
Данный пример предполагает, что в той же директории находятся файлы `zapret-lib.lua` - библиотека хелперов на Lua и `zapret-antidpi.lua` - библиотека базовых стратегий.
|
||||
`--lua-init` может содержать Lua код в виде строки. Так удобно писать простой код, например присвоить константу переменной, чтобы не создавать файлы ради этой мелочи.
|
||||
Либо подцепляется файл, если значение параметра начинается с `@`. Код из `--lua-init` выполняется 1 раз при старте.
|
||||
|
||||
Далее указаны параметры `--lua-desync`. Они содержат имя LUA функции, вызываемой при обработке каждого пакета, проходящего через профиль мультистратегии.
|
||||
Далее указаны параметры `--lua-desync`. Они содержат имя Lua функции, вызываемой при обработке каждого пакета, проходящего через профиль мультистратегии.
|
||||
После двоеточия и через двоеточия следуют параметры для данной функции в формате `param[=value]`. В примере реализована стратегия
|
||||
|
||||
```
|
||||
@@ -108,7 +129,7 @@ nfqws --qnum 200 --debug \
|
||||
Тип пейлоада - тип данных, содержащихся в пакете или группе пакетов. Например, протокол соединения может быть tls, а пейлоады - tls_client_hello, tls_server_hello, unknown.
|
||||
|
||||
Другое важное отличие - отсутствие жестко определенных фаз десинхронизации. То, что вы раньше писали как `fake,multisplit` реализуется двумя
|
||||
последовательно вызываемыми LUA функциями. Их может быть столько, сколько нужно, учитывая логику прохождения пакетов и операций с ними, и у каждой могут быть свои параметры.
|
||||
последовательно вызываемыми Lua функциями. Их может быть столько, сколько нужно, учитывая логику прохождения пакетов и операций с ними, и у каждой могут быть свои параметры.
|
||||
Может даже несколько раз вызываться одна и так же функция с разными параметрами. Так, например, можно послать несколько фейков, причем с разными фулингами.
|
||||
Конкретный вызов `--lua-desync` функции называется инстансом. Инстанс - это связка имени функции, номера вызова внутри профиля и номера самого профиля.
|
||||
Это похоже на одну программу, которую можно запустить много раз с разными параметрами.
|
||||
@@ -116,11 +137,11 @@ nfqws --qnum 200 --debug \
|
||||
Другое немаловажное отличие - поддержка автоматической tcp сегментации средствами `zapret-lib.lua`. Вам больше не нужно думать о размерах отсылаемых tcp пакетов.
|
||||
По каждому соединению отслеживается MSS. Если пакет не влезает в MSS, выполняется сегментация.
|
||||
Например, это может случиться при отправке tls фейка с kyber. Или если вы режете kyber tls так, что одна из частей получается размером 1600 байт,
|
||||
что, очевидно, не влезает в MTU. Или если вы задали seqovl=10000. В *nfqws1* такое значение вызвало бы ошибку. Функция LUA `rawsend_dissect_segmented` отправит
|
||||
что, очевидно, не влезает в MTU. Или если вы задали seqovl=10000. В *nfqws1* такое значение вызвало бы ошибку. Функция Lua `rawsend_dissect_segmented` отправит
|
||||
несколько tcp сегментов с начальным sequence -10000 общим размером 10000 байт, в последнем из которых будет кусок оригинального сообщения.
|
||||
|
||||
В *nfqws2* нет жестко зашитых параметров кастомных фейков типа `--dpi-desync-fake-tls`, `dpi-desync-fake-http` и тд.
|
||||
Вместо них есть блобы. Блоб (blob) - это переменная LUA типа *string*, содержащая блок двоичных данных произвольной длины. От 1 байта до гигабайтов.
|
||||
Вместо них есть блобы. Блоб (blob) - это переменная Lua типа *string*, содержащая блок двоичных данных произвольной длины. От 1 байта до гигабайтов.
|
||||
*nfqws2* автоматически инициализирует блобы со стандартными фейками tls, http, quic, как это и было в *nfqws1*.
|
||||
Блобы могут быть заданы как hex-строка прямо в параметре desync функции, либо пред-загружены при старте с помощью параметра `--blob=name:0xHEX|[+ofs]@filename`
|
||||
|
||||
@@ -153,15 +174,15 @@ range задается как `mX-mY`, `mX<mY`, `-mY`, `<mY`, `mX-`.
|
||||
Следующий профиль снова принимает значения по умолчанию.
|
||||
|
||||
Что будет, если вы не напишите фильтр `--payload` для fake или multisplit ? В *nfqws1* без `--dpi-desync-any-protocol` они работали только по известным пейлоадам.
|
||||
В *nfqws2* "any protocol" - режим по умолчанию. Однако, функции из библиотеки `zapret-antidpi.lua` написаны так, что по умолчанию работают только по известные пейлоадам
|
||||
В *nfqws2* "any protocol" - режим по умолчанию. Однако, функции из библиотеки `zapret-antidpi.lua` написаны так, что по умолчанию работают только по известным пейлоадам
|
||||
и не работают по пустым пакетам или unknown - точно так же, как это было в *nfqws1*.
|
||||
Но лучше все-же писать фильтры `--payload`, потому что они работают на уровне C кода, который выполняется существенно быстрее, чем LUA.
|
||||
Но лучше все-же писать фильтры `--payload`, потому что они работают на уровне C кода, который выполняется существенно быстрее, чем Lua.
|
||||
|
||||
Диссект пакета проходит поочередно по всем `--lua-desync` инстансам профиля, для которых не выполняется условие отсечения (cutoff).
|
||||
Отсечение может быть по range, payload или добровольное отсечение. Последний вариант - когда инстанс сам отказывается обрабатывать пакеты
|
||||
по входящему, исходящему или обоим направлениям. Например, задача стратегии wsize - отреагировать только на пакет с tcp флагами SYN,ACK. После этого он не нужен, в коде вызывается функция отсечения.
|
||||
Это сделано для экономии ресурсов процессора.
|
||||
Если все инстансы в профиле точно никогда больше не будут вызваны по соединению + направлению - вошли в превышение верхней границы range или выполнили добровольный cutoff, то движок LUA не вызывается вообще.
|
||||
Если все инстансы в профиле точно никогда больше не будут вызваны по соединению + направлению - вошли в превышение верхней границы range или выполнили добровольный cutoff, то движок Lua не вызывается вообще.
|
||||
|
||||
От инстанса к инстансу содержимое диссекта может ими меняться. Следующий инстанс видит изменения предыдущего.
|
||||
Каждый инстанс выносит свой вердикт - что делать с текущим диссектом. VERDICT_PASS - означает отправить как есть,
|
||||
@@ -287,22 +308,21 @@ nfqws2 --lua-desync=send:ipfrag:ipfrag_pos_udp=8 --lua-desync=drop
|
||||
Но это решаемо. А что не решаемо - это перехват вторых частей kyber tls hello. Их невозможно опознать без связи с предыдущими фрагментами. Поэтому перехватывается весь порт.
|
||||
Для HTTP вопрос решаемый, поскольку там нет реассемблирования запросов, но http сейчас стал настолько редким, что и смысла нет заморачиваться.
|
||||
|
||||
Везде расставлены фильтры профиля мультистратегии `--filter-l7`, фильтры по `--out-range` и по `--payload`.
|
||||
Зачем ? В основном для сокращения вызовов LUA кода, который заведомо медленнее C кода.
|
||||
Если пакет не попадет в профили с LUA - ни о каком вызове кода LUA речи быть не может.
|
||||
Если пакет попал в профиль с LUA, то после первых 10 пакетов с данными наступает отсечение по верхней границе range. Все LUA инстансы входят в состояние instance cutoff,
|
||||
соединение входит в состояние "lua cutoff" по направлению "out". Значит вызовов LUA не будет вообще. Не просто вызовов, а даже обращения к движку LUA
|
||||
с какой-либо целью. Будет только C код, который посмотрит на признак "cutoff" и сразу же отпустит пакет.
|
||||
Везде расставлены фильтры профиля мультистратегии `--filter-l7`, фильтры по `--out-range` и по `--payload`. Зачем ? В основном для сокращения вызовов Lua кода, который заведомо медленнее C кода.
|
||||
Если пакет не попадет в профили с Lua - ни о каком вызове кода Lua речи быть не может. Если пакет попал в профиль с Lua, то после первых 10 пакетов с данными наступает отсечение по верхней границе range. Все Lua инстансы входят в состояние instance cutoff, соединение входит в состояние "lua cutoff" по направлению "out". Значит вызовов Lua не будет вообще. Не просто вызовов, а даже обращения к движку Lua с какой-либо целью. Будет только C код, который посмотрит на признак "cutoff" и сразу же отпустит пакет.
|
||||
|
||||
Так же везде расставлены фильтры по payload type. Отчасти так же с целью сократить вызовы LUA даже в пределах первых 10 пакетов с данными.
|
||||
Почему именно `-d10` ? Чтобы хватило для отработки большинства вариантов стратегий, учитывая возможные ретрансмиссии и плохую связь. В winws2 по умолчанию включен параметр `--wf-tcp-empty=0`. Он блокирует перехват пустых пакетов с ACK, что позволяет примерно в 2 раза сэкономить на процессоре при интенсивных скачиваниях. Пустые ACK в большинстве стратегий не нужны. Но это же и ломает счетчик "n" - он не будет показывать реальное количество пакетов по соединению. Счетчик "d" работать будет как надо.
|
||||
|
||||
Почему нет "-d10" на udp ? Потому что используется windivert фильтр на пейлоад. Счетчики будут считать не реальное количество пакетов в потоке, а количество перехваченных с отфильтрованными пейлоадами. Причем если интервал между ними будет более 1 минуты, то счет будет начинаться заново, поскольку таймаут udp по умолчанию - 60 сек. После таймаута запись conntrack будет удалена. Следующий пакет пойдет как новый поток.
|
||||
|
||||
Так же везде расставлены фильтры по payload type. Отчасти так же с целью сократить вызовы Lua даже в пределах первых 10 пакетов с данными.
|
||||
С другой стороны, даже при совпадении протокола соединения (`--filter-l7`) может пробежать не интересующий нас пейлоад.
|
||||
По умолчанию многие функции из `zapret-antidpi.lua` реагируют только на известные типы пейлоада, но не на конкретные, а на любые известные.
|
||||
Если допустить малореальный, но гипотетически возможный сценарий, что в рамках протокола http будет отправлен блок данных с tls или фраза, похожая на сообщение из xmpp,
|
||||
то тип пейлоада выскочит tls_client_hello или xmpp_stream, например. Лучше от этого сразу уберечься. Тем более что в других видах протоколов - xmpp, например, -
|
||||
Если допустить малореальный, но гипотетически возможный сценарий, что в рамках протокола http будет отправлен блок данных с tls или фраза, похожая на сообщение из xmpp, то тип пейлоада выскочит tls_client_hello или xmpp_stream, например. Лучше от этого сразу уберечься. Тем более что в других видах протоколов - xmpp, например, -
|
||||
пейлоады могут проскакивать нескольких типов вполне ожидаемо. Но работать надо не по всем.
|
||||
|
||||
В фейке для TLS по умолчанию - fake_default_tls - однократно при старте меняется SNI с "www.microsoft.com" на случайный и рандомизируется поле "random" в TLS handshake.
|
||||
Это делается простой строчкой LUA кода. Больше нет никаких специальных параметров *nfqws2* для модификации пейлоадов.
|
||||
Это делается простой строчкой Lua кода. Больше нет никаких специальных параметров *nfqws2* для модификации пейлоадов.
|
||||
В профиле для youtube на лету меняется SNI на "www.google.com", копируется поле TLS "session id" с обрабатываемого в данный момент TLS handshake.
|
||||
|
||||
```
|
||||
@@ -348,17 +368,14 @@ start "zapret: http,https,quic" /min "%~dp0winws2.exe" ^
|
||||
--lua-desync=multidisorder:pos=midsld ^
|
||||
--new ^
|
||||
--filter-udp=443 --filter-l7=quic --hostlist="%~dp0files\list-youtube.txt" ^
|
||||
--out-range=-d10 ^
|
||||
--payload=quic_initial ^
|
||||
--lua-desync=fake:blob=quic_google:repeats=11 ^
|
||||
--new ^
|
||||
--filter-udp=443 --filter-l7=quic ^
|
||||
--out-range=-d10 ^
|
||||
--payload=quic_initial ^
|
||||
--lua-desync=fake:blob=fake_default_quic:repeats=11 ^
|
||||
--new ^
|
||||
--filter-l7=wireguard,stun,discord ^
|
||||
--out-range=-d10 ^
|
||||
--payload=wireguard_initiation,wireguard_cookie,stun,discord_ip_discovery ^
|
||||
--lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2
|
||||
```
|
||||
@@ -370,9 +387,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 паттерна.
|
||||
|
||||
@@ -397,10 +414,87 @@ nfqws2 \
|
||||
### Какие есть еще параметры
|
||||
|
||||
Как узнать какие есть еще функции и какие у них бывают параметры ? Смотрите `zapret-antidpi.lua`. Перед каждой функцией подробно описано какие параметры она берет.
|
||||
Описание стандартных блоков параметров есть в начале. Позже - по мере сил и возможностей - будет писаться талмуд - справочник с руководством по программированию
|
||||
*nfqws2* и описание стандартных библиотек.
|
||||
Описание стандартных блоков параметров есть в начале.
|
||||
Или сразу читайте [талмуд](manual.md) . Там все документировано.
|
||||
|
||||
### Очень важный совет
|
||||
|
||||
Научитесь пользоваться `--debug` логом. Без него будет очень сложно понять *nfqws2* на начальном этапе и приспособиться к новой схеме.
|
||||
Ошибок будет много. Особенно, когда вы начнете писать свой LUA код. Их надо читать.
|
||||
Ошибок будет много. Особенно, когда вы начнете писать свой Lua код. Их надо читать.
|
||||
|
||||
### Не только лишь автономный обман DPI
|
||||
|
||||
Рабочий тестовый пример icmp обфускатора udp от винды к серверу на vps.
|
||||
Для теста используем wireguard. Ничего в конфигах менять не надо - wireguard будет думать, что он работает по udp, но на самом деле он преобразуется в пинги icmp, которые могут проходить NAT. Размер пакетов не изменяется, потому проблемы MTU нет.
|
||||
|
||||
Будем загонять исходящие с клиента в icmp type 8 (echo request) code 199 , исходящие с сервера в icmp type 0 (echo reply) code 199.
|
||||
Код у обоих концов делаем одинаковый, иначе NAT не соотнесет. Без NAT можно коды делать разными для клиента и сервера.
|
||||
Особый icmp code нужен для фильтрации от обычных пингов.
|
||||
|
||||
По стандарту код должен быть 0, но на практике с большой вероятностью работают любые коды.
|
||||
Разные имплементации NAT теоретически могут фильтровать ненулевой код, соотносить или не соотносить код вместе с identifier. Linux NAT соотносит.
|
||||
При любых проблемах убираем wireguard, ставим netcat с обоих концов и пробуем общаться, посматривая в wireshark.
|
||||
Всегда можно откатиться на нулевой код, но тогда у сервера без фильтра по IP клиента будет плохая защита от обычных пингов - все они будут преобразовываться в udp и направляться в wireguard,
|
||||
который будет их игнорировать, поскольку передается мусор. Сервер перестанет пингаться.
|
||||
|
||||
Другой способ избежать проблемы и уйти от стандартных пингов - использовать другие типы icmp. Работающие пары, пробрасываемые Linux NAT :
|
||||
|
||||
- `ctype=8:stype=0` - echo request - echo reply (используется по умолчанию)
|
||||
- `ctype=13:stype=14` - timestamp - timestamp reply
|
||||
- `ctype=15:stype=16` - information request - information reply
|
||||
- `ctype=17:stype=18` - address mask request - address mask reply
|
||||
|
||||
На провайдерских NAT или на аппаратном ускорении роутера может быть другой расклад по работающим парам.
|
||||
Нужно пробовать и смотреть что выходит в сеть после NAT и что приходит на сервер.
|
||||
Например, Linux NAT вообще не пробрасывает type 42 - extended echo request. Но аппаратная железка может пробросить и провайдер тоже.
|
||||
|
||||
Кто знает, может быть DPI настроен сечь icmp тоннели на стандартных пингах, а на других типах icmp нет ?
|
||||
|
||||
|
||||
wireguard server - `1.2.3.4:5555`
|
||||
|
||||
```
|
||||
table ip ztest {
|
||||
chain post {
|
||||
type filter hook output priority mangle; policy accept;
|
||||
meta mark & 0x40000000 == 0x00000000 udp sport 5555 queue flags bypass to 200
|
||||
}
|
||||
|
||||
chain pre {
|
||||
type filter hook input priority mangle; policy accept;
|
||||
meta mark & 0x40000000 == 0x00000000 icmp type echo-request icmp code 199 queue flags bypass to 200
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
nfqws2 --qnum 200 --server
|
||||
--lua-init=@/opt/zapret2/lua/zapret-lib.lua
|
||||
--lua-init=@/opt/zapret2/lua/zapret-obfs.lua
|
||||
--in-range=a
|
||||
--lua-desync=udp2icmp:ccode=199:scode=199
|
||||
```
|
||||
|
||||
Клиент на винде :
|
||||
|
||||
```
|
||||
winws2
|
||||
--wf-icmp-in=0:199 --wf-udp-out=5555
|
||||
--wf-raw-filter="ip.SrcAddr=1.2.3.4 or ip.DstAddr=1.2.3.4"
|
||||
--lua-init=@lua/zapret-lib.lua
|
||||
--lua-init=@lua/zapret-obfs.lua
|
||||
--in-range=a
|
||||
--lua-desync=udp2icmp:ccode=199:scode=199
|
||||
```
|
||||
|
||||
Все лишнее отсекается в ядре в windivert - проц зазря не грузит.
|
||||
--wf-raw-filter сочетается со всем остальным собранным конструктором по AND. Отсекает по IP адресу сервера.
|
||||
--wf-icmp-in отсекает входящие icmp типа 0 с кодом 199.
|
||||
|
||||
И включаем wireguard.
|
||||
В шарке сплошняком пинги и реплаи с кодом 199
|
||||
|
||||
Если IP клиента постоянен, можно дополнительно на стороне сервера сделать фильтр по IP клиента.
|
||||
|
||||
Дополнительно можно сделать dataxor=blob на обоих концах, чтобы поксорить пейлоад.
|
||||
blob растягивается на размер пакета как pattern. Можно использовать от 1 hex byte до специально нагенеренного рандома. На обоих концах должен быть одинаковый
|
||||
|
||||
BIN
files/fake/bgp_open.bin
Normal file
BIN
files/fake/bgp_open.bin
Normal file
Binary file not shown.
BIN
files/fake/bitcoin.bin
Normal file
BIN
files/fake/bitcoin.bin
Normal file
Binary file not shown.
BIN
files/fake/dns.bin
Normal file
BIN
files/fake/dns.bin
Normal file
Binary file not shown.
BIN
files/fake/dtls_serverhello.bin
Normal file
BIN
files/fake/dtls_serverhello.bin
Normal file
Binary file not shown.
BIN
files/fake/ntp4.bin
Normal file
BIN
files/fake/ntp4.bin
Normal file
Binary file not shown.
BIN
files/fake/quic2_example_com.bin
Normal file
BIN
files/fake/quic2_example_com.bin
Normal file
Binary file not shown.
4
files/fake/rtsp_options.bin
Normal file
4
files/fake/rtsp_options.bin
Normal 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
1
files/fake/smtp_ehlo.bin
Normal file
@@ -0,0 +1 @@
|
||||
EHLO delta.peach.mil
|
||||
BIN
files/fake/snmp_get_next_request.bin
Normal file
BIN
files/fake/snmp_get_next_request.bin
Normal file
Binary file not shown.
BIN
files/fake/tls_alert.bin
Normal file
BIN
files/fake/tls_alert.bin
Normal file
Binary file not shown.
BIN
files/fake/tls_clienthello_google_com_tlsrec.bin
Normal file
BIN
files/fake/tls_clienthello_google_com_tlsrec.bin
Normal file
Binary file not shown.
BIN
files/fake/tls_serverhello_google_com_tls13.bin
Normal file
BIN
files/fake/tls_serverhello_google_com_tls13.bin
Normal file
Binary file not shown.
@@ -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
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
WEBSERVER_DEFAULT_STRATEGY="
|
||||
--server
|
||||
--payload http_reply,tls_server_hello --lua-desync=fake:blob=0x00000000000000000000000000000000:badsum:repeats=2 --lua-desync=multisplit
|
||||
--payload empty --lua-desync=synack_split"
|
||||
--payload=http_reply,tls_server_hello --lua-desync=fake:blob=0x00000000000000000000000000000000:badsum:repeats=2 --lua-desync=multisplit
|
||||
--payload=empty --lua-desync=synack_split"
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_WEBSERVER="${NFQWS_OPT_DESYNC_WEBSERVER:-$WEBSERVER_DEFAULT_STRATEGY}"
|
||||
|
||||
@@ -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}"
|
||||
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
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_DISCORD_MEDIA="${NFQWS_OPT_DESYNC_DISCORD_MEDIA:---payload discord_ip_discovery --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
|
||||
NFQWS_OPT_DESYNC_DISCORD_MEDIA="${NFQWS_OPT_DESYNC_DISCORD_MEDIA:---payload=discord_ip_discovery --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
|
||||
DISCORD_MEDIA_PORT_RANGE="${DISCORD_MEDIA_PORT_RANGE:-50000-50099}"
|
||||
|
||||
alloc_dnum DNUM_DISCORD_MEDIA
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
# this custom script demonstrates how to launch extra nfqws instance limited by ipset
|
||||
|
||||
# can override in config :
|
||||
NFQWS_MY1_OPT="${NFQWS_MY1_OPT:---filter-udp=* --payload known,unknown --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2:payload=all --new --filter-tcp=* --payload=known,unknown --lua-desync=multisplit}"
|
||||
NFQWS_MY1_SUBNETS4="${NFQWS_MY1_SUBNETS4:-173.194.0.0/16 108.177.0.0/17 74.125.0.0/16 64.233.160.0/19 172.217.0.0/16}"
|
||||
NFQWS_MY1_SUBNETS6="${NFQWS_MY1_SUBNETS6:-2a00:1450::/29}"
|
||||
NFQWS_MY1_PORTS_TCP=${NFQWS_MY1_PORTS_TCP:-$NFQWS_PORTS_TCP}
|
||||
NFQWS_MY1_PORTS_UDP=${NFQWS_MY1_PORTS_UDP:-$NFQWS_PORTS_UDP}
|
||||
NFQWS_MY1_TCP_PKT_OUT=${NFQWS_MY1_TCP_PKT_OUT:-$NFQWS_TCP_PKT_OUT}
|
||||
NFQWS_MY1_UDP_PKT_OUT=${NFQWS_MY1_UDP_PKT_OUT:-$NFQWS_UDP_PKT_OUT}
|
||||
NFQWS_MY1_TCP_PKT_IN=${NFQWS_MY1_TCP_PKT_IN:-$NFQWS_TCP_PKT_IN}
|
||||
NFQWS_MY1_UDP_PKT_IN=${NFQWS_MY1_UDP_PKT_IN:-$NFQWS_UDP_PKT_IN}
|
||||
NFQWS2_MY1_OPT="${NFQWS2_MY1_OPT:---filter-udp=* --payload=known,unknown --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2:payload=all --new --filter-tcp=* --payload=known,unknown --lua-desync=multisplit}"
|
||||
NFQWS2_MY1_SUBNETS4="${NFQWS2_MY1_SUBNETS4:-173.194.0.0/16 108.177.0.0/17 74.125.0.0/16 64.233.160.0/19 172.217.0.0/16}"
|
||||
NFQWS2_MY1_SUBNETS6="${NFQWS2_MY1_SUBNETS6:-2a00:1450::/29}"
|
||||
NFQWS2_MY1_PORTS_TCP=${NFQWS2_MY1_PORTS_TCP:-$NFQWS2_PORTS_TCP}
|
||||
NFQWS2_MY1_PORTS_UDP=${NFQWS2_MY1_PORTS_UDP:-$NFQWS2_PORTS_UDP}
|
||||
NFQWS2_MY1_TCP_PKT_OUT=${NFQWS2_MY1_TCP_PKT_OUT:-$NFQWS2_TCP_PKT_OUT}
|
||||
NFQWS2_MY1_UDP_PKT_OUT=${NFQWS2_MY1_UDP_PKT_OUT:-$NFQWS2_UDP_PKT_OUT}
|
||||
NFQWS2_MY1_TCP_PKT_IN=${NFQWS2_MY1_TCP_PKT_IN:-$NFQWS2_TCP_PKT_IN}
|
||||
NFQWS2_MY1_UDP_PKT_IN=${NFQWS2_MY1_UDP_PKT_IN:-$NFQWS2_UDP_PKT_IN}
|
||||
|
||||
NFQWS_MY1_IPSET_SIZE=${NFQWS_MY1_IPSET_SIZE:-4096}
|
||||
NFQWS_MY1_IPSET_OPT="${NFQWS_MY1_IPSET_OPT:-hash:net hashsize 8192 maxelem $NFQWS_MY1_IPSET_SIZE}"
|
||||
NFQWS2_MY1_IPSET_SIZE=${NFQWS2_MY1_IPSET_SIZE:-4096}
|
||||
NFQWS2_MY1_IPSET_OPT="${NFQWS2_MY1_IPSET_OPT:-hash:net hashsize 8192 maxelem $NFQWS2_MY1_IPSET_SIZE}"
|
||||
|
||||
alloc_dnum DNUM_NFQWS_MY1
|
||||
alloc_qnum QNUM_NFQWS_MY1
|
||||
NFQWS_MY1_NAME4=my1nfqws4
|
||||
NFQWS_MY1_NAME6=my1nfqws6
|
||||
alloc_dnum DNUM_NFQWS2_MY1
|
||||
alloc_qnum QNUM_NFQWS2_MY1
|
||||
NFQWS2_MY1_NAME4=my1nfqws4
|
||||
NFQWS2_MY1_NAME6=my1nfqws6
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local opt="--qnum=$QNUM_NFQWS_MY1 $NFQWS_MY1_OPT"
|
||||
do_nfqws $1 $DNUM_NFQWS_MY1 "$opt"
|
||||
local opt="--qnum=$QNUM_NFQWS2_MY1 $NFQWS2_MY1_OPT"
|
||||
do_nfqws $1 $DNUM_NFQWS2_MY1 "$opt"
|
||||
}
|
||||
|
||||
zapret_custom_firewall()
|
||||
@@ -32,103 +32,103 @@ zapret_custom_firewall()
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local f4 f6 subnet
|
||||
local NFQWS_MY1_PORTS_TCP=$(replace_char - : $NFQWS_MY1_PORTS_TCP)
|
||||
local NFQWS_MY1_PORTS_UDP=$(replace_char - : $NFQWS_MY1_PORTS_UDP)
|
||||
local NFQWS2_MY1_PORTS_TCP=$(replace_char - : $NFQWS2_MY1_PORTS_TCP)
|
||||
local NFQWS2_MY1_PORTS_UDP=$(replace_char - : $NFQWS2_MY1_PORTS_UDP)
|
||||
|
||||
[ "$1" = 1 -a "$DISABLE_IPV4" != 1 ] && {
|
||||
ipset create $NFQWS_MY1_NAME4 $NFQWS_MY1_IPSET_OPT family inet 2>/dev/null
|
||||
ipset flush $NFQWS_MY1_NAME4
|
||||
for subnet in $NFQWS_MY1_SUBNETS4; do
|
||||
echo add $NFQWS_MY1_NAME4 $subnet
|
||||
ipset create $NFQWS2_MY1_NAME4 $NFQWS2_MY1_IPSET_OPT family inet 2>/dev/null
|
||||
ipset flush $NFQWS2_MY1_NAME4
|
||||
for subnet in $NFQWS2_MY1_SUBNETS4; do
|
||||
echo add $NFQWS2_MY1_NAME4 $subnet
|
||||
done | ipset -! restore
|
||||
}
|
||||
[ "$1" = 1 -a "$DISABLE_IPV6" != 1 ] && {
|
||||
ipset create $NFQWS_MY1_NAME6 $NFQWS_MY1_IPSET_OPT family inet6 2>/dev/null
|
||||
ipset flush $NFQWS_MY1_NAME6
|
||||
for subnet in $NFQWS_MY1_SUBNETS6; do
|
||||
echo add $NFQWS_MY1_NAME6 $subnet
|
||||
ipset create $NFQWS2_MY1_NAME6 $NFQWS2_MY1_IPSET_OPT family inet6 2>/dev/null
|
||||
ipset flush $NFQWS2_MY1_NAME6
|
||||
for subnet in $NFQWS2_MY1_SUBNETS6; do
|
||||
echo add $NFQWS2_MY1_NAME6 $subnet
|
||||
done | ipset -! restore
|
||||
}
|
||||
|
||||
[ -n "$NFQWS_MY1_PORTS_TCP" ] && {
|
||||
[ -n "$NFQWS_MY1_TCP_PKT_OUT" -a "$NFQWS_MY1_TCP_PKT_OUT" != 0 ] && {
|
||||
f4="-p tcp -m multiport --dports $NFQWS_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS_MY1_TCP_PKT_OUT -m set --match-set"
|
||||
f6="$f4 $NFQWS_MY1_NAME6 dst"
|
||||
f4="$f4 $NFQWS_MY1_NAME4 dst"
|
||||
fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
[ -n "$NFQWS2_MY1_PORTS_TCP" ] && {
|
||||
[ -n "$NFQWS2_MY1_TCP_PKT_OUT" -a "$NFQWS2_MY1_TCP_PKT_OUT" != 0 ] && {
|
||||
f4="-p tcp -m multiport --dports $NFQWS2_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS2_MY1_TCP_PKT_OUT -m set --match-set"
|
||||
f6="$f4 $NFQWS2_MY1_NAME6 dst"
|
||||
f4="$f4 $NFQWS2_MY1_NAME4 dst"
|
||||
fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS2_MY1
|
||||
}
|
||||
[ -n "$NFQWS_MY1_TCP_PKT_IN" -a "$NFQWS_MY1_TCP_PKT_IN" != 0 ] && {
|
||||
f4="-p tcp -m multiport --sports $NFQWS_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS_MY1_TCP_PKT_IN -m set --match-set"
|
||||
f6="$f4 $NFQWS_MY1_NAME6 src"
|
||||
f4="$f4 $NFQWS_MY1_NAME4 src"
|
||||
fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
[ -n "$NFQWS2_MY1_TCP_PKT_IN" -a "$NFQWS2_MY1_TCP_PKT_IN" != 0 ] && {
|
||||
f4="-p tcp -m multiport --sports $NFQWS2_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS2_MY1_TCP_PKT_IN -m set --match-set"
|
||||
f6="$f4 $NFQWS2_MY1_NAME6 src"
|
||||
f4="$f4 $NFQWS2_MY1_NAME4 src"
|
||||
fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS2_MY1
|
||||
}
|
||||
}
|
||||
[ -n "$NFQWS_MY1_PORTS_UDP" ] && {
|
||||
[ -n "$NFQWS_MY1_UDP_PKT_OUT" -a "$NFQWS_MY1_UDP_PKT_OUT" != 0 ] && {
|
||||
f4="-p udp -m multiport --dports $NFQWS_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS_MY1_UDP_PKT_OUT -m set --match-set"
|
||||
f6="$f4 $NFQWS_MY1_NAME6 dst"
|
||||
f4="$f4 $NFQWS_MY1_NAME4 dst"
|
||||
fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
[ -n "$NFQWS2_MY1_PORTS_UDP" ] && {
|
||||
[ -n "$NFQWS2_MY1_UDP_PKT_OUT" -a "$NFQWS2_MY1_UDP_PKT_OUT" != 0 ] && {
|
||||
f4="-p udp -m multiport --dports $NFQWS2_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS2_MY1_UDP_PKT_OUT -m set --match-set"
|
||||
f6="$f4 $NFQWS2_MY1_NAME6 dst"
|
||||
f4="$f4 $NFQWS2_MY1_NAME4 dst"
|
||||
fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS2_MY1
|
||||
}
|
||||
[ -n "$NFQWS_MY1_UDP_PKT_IN" -a "$NFQWS_MY1_UDP_PKT_IN" != 0 ] && {
|
||||
f4="-p udp -m multiport --sports $NFQWS_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS_MY1_UDP_PKT_IN -m set --match-set"
|
||||
f6="$f4 $NFQWS_MY1_NAME6 src"
|
||||
f4="$f4 $NFQWS_MY1_NAME4 src"
|
||||
fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
[ -n "$NFQWS2_MY1_UDP_PKT_IN" -a "$NFQWS2_MY1_UDP_PKT_IN" != 0 ] && {
|
||||
f4="-p udp -m multiport --sports $NFQWS2_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS2_MY1_UDP_PKT_IN -m set --match-set"
|
||||
f6="$f4 $NFQWS2_MY1_NAME6 src"
|
||||
f4="$f4 $NFQWS2_MY1_NAME4 src"
|
||||
fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS2_MY1
|
||||
}
|
||||
}
|
||||
|
||||
[ "$1" = 1 ] || {
|
||||
ipset destroy $NFQWS_MY1_NAME4 2>/dev/null
|
||||
ipset destroy $NFQWS_MY1_NAME6 2>/dev/null
|
||||
ipset destroy $NFQWS2_MY1_NAME4 2>/dev/null
|
||||
ipset destroy $NFQWS2_MY1_NAME6 2>/dev/null
|
||||
}
|
||||
}
|
||||
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
local f4 f6 subnets
|
||||
local first_packets_only="$nft_connbytes 1-$NFQWS_MY1_PKT_OUT"
|
||||
local first_packets_only="$nft_connbytes 1-$NFQWS2_MY1_PKT_OUT"
|
||||
|
||||
[ "$DISABLE_IPV4" != 1 ] && {
|
||||
make_comma_list subnets $NFQWS_MY1_SUBNETS4
|
||||
nft_create_set $NFQWS_MY1_NAME4 "type ipv4_addr; size $NFQWS_MY1_IPSET_SIZE; auto-merge; flags interval;"
|
||||
nft_flush_set $NFQWS_MY1_NAME4
|
||||
nft_add_set_element $NFQWS_MY1_NAME4 "$subnets"
|
||||
make_comma_list subnets $NFQWS2_MY1_SUBNETS4
|
||||
nft_create_set $NFQWS2_MY1_NAME4 "type ipv4_addr; size $NFQWS2_MY1_IPSET_SIZE; auto-merge; flags interval;"
|
||||
nft_flush_set $NFQWS2_MY1_NAME4
|
||||
nft_add_set_element $NFQWS2_MY1_NAME4 "$subnets"
|
||||
}
|
||||
[ "$DISABLE_IPV6" != 1 ] && {
|
||||
make_comma_list subnets $NFQWS_MY1_SUBNETS6
|
||||
nft_create_set $NFQWS_MY1_NAME6 "type ipv6_addr; size $NFQWS_MY1_IPSET_SIZE; auto-merge; flags interval;"
|
||||
nft_flush_set $NFQWS_MY1_NAME6
|
||||
nft_add_set_element $NFQWS_MY1_NAME6 "$subnets"
|
||||
make_comma_list subnets $NFQWS2_MY1_SUBNETS6
|
||||
nft_create_set $NFQWS2_MY1_NAME6 "type ipv6_addr; size $NFQWS2_MY1_IPSET_SIZE; auto-merge; flags interval;"
|
||||
nft_flush_set $NFQWS2_MY1_NAME6
|
||||
nft_add_set_element $NFQWS2_MY1_NAME6 "$subnets"
|
||||
}
|
||||
|
||||
[ -n "$NFQWS_MY1_PORTS_TCP" ] && {
|
||||
[ -n "$NFQWS_MY1_TCP_PKT_OUT" -a "$NFQWS_MY1_TCP_PKT_OUT" != 0 ] && {
|
||||
f4="tcp dport {$NFQWS_MY1_PORTS_TCP} $(nft_first_packets $NFQWS_MY1_TCP_PKT_OUT)"
|
||||
f6="$f4 ip6 daddr @$NFQWS_MY1_NAME6"
|
||||
f4="$f4 ip daddr @$NFQWS_MY1_NAME4"
|
||||
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
[ -n "$NFQWS2_MY1_PORTS_TCP" ] && {
|
||||
[ -n "$NFQWS2_MY1_TCP_PKT_OUT" -a "$NFQWS2_MY1_TCP_PKT_OUT" != 0 ] && {
|
||||
f4="tcp dport {$NFQWS2_MY1_PORTS_TCP} $(nft_first_packets $NFQWS2_MY1_TCP_PKT_OUT)"
|
||||
f6="$f4 ip6 daddr @$NFQWS2_MY1_NAME6"
|
||||
f4="$f4 ip daddr @$NFQWS2_MY1_NAME4"
|
||||
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS2_MY1
|
||||
}
|
||||
[ -n "$NFQWS_MY1_TCP_PKT_IN" -a "$NFQWS_MY1_TCP_PKT_IN" != 0 ] && {
|
||||
f4="tcp sport {$NFQWS_MY1_PORTS_TCP} $(nft_first_packets $NFQWS_MY1_TCP_PKT_IN)"
|
||||
f6="$f4 ip6 saddr @$NFQWS_MY1_NAME6"
|
||||
f4="$f4 ip saddr @$NFQWS_MY1_NAME4"
|
||||
nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
[ -n "$NFQWS2_MY1_TCP_PKT_IN" -a "$NFQWS2_MY1_TCP_PKT_IN" != 0 ] && {
|
||||
f4="tcp sport {$NFQWS2_MY1_PORTS_TCP} $(nft_first_packets $NFQWS2_MY1_TCP_PKT_IN)"
|
||||
f6="$f4 ip6 saddr @$NFQWS2_MY1_NAME6"
|
||||
f4="$f4 ip saddr @$NFQWS2_MY1_NAME4"
|
||||
nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS2_MY1
|
||||
}
|
||||
}
|
||||
[ -n "$NFQWS_MY1_PORTS_UDP" ] && {
|
||||
[ -n "$NFQWS_MY1_UDP_PKT_OUT" -a "$NFQWS_MY1_UDP_PKT_OUT" != 0 ] && {
|
||||
f4="udp dport {$NFQWS_MY1_PORTS_UDP} $(nft_first_packets $NFQWS_MY1_UDP_PKT_OUT)"
|
||||
f6="$f4 ip6 daddr @$NFQWS_MY1_NAME6"
|
||||
f4="$f4 ip daddr @$NFQWS_MY1_NAME4"
|
||||
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
[ -n "$NFQWS2_MY1_PORTS_UDP" ] && {
|
||||
[ -n "$NFQWS2_MY1_UDP_PKT_OUT" -a "$NFQWS2_MY1_UDP_PKT_OUT" != 0 ] && {
|
||||
f4="udp dport {$NFQWS2_MY1_PORTS_UDP} $(nft_first_packets $NFQWS2_MY1_UDP_PKT_OUT)"
|
||||
f6="$f4 ip6 daddr @$NFQWS2_MY1_NAME6"
|
||||
f4="$f4 ip daddr @$NFQWS2_MY1_NAME4"
|
||||
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS2_MY1
|
||||
}
|
||||
[ -n "$NFQWS_MY1_UDP_PKT_IN" -a "$NFQWS_MY1_UDP_PKT_IN" != 0 ] && {
|
||||
f4="udp sport {$NFQWS_MY1_PORTS_UDP} $(nft_first_packets $NFQWS_MY1_UDP_PKT_IN)"
|
||||
f6="$f4 ip6 saddr @$NFQWS_MY1_NAME6"
|
||||
f4="$f4 ip saddr @$NFQWS_MY1_NAME4"
|
||||
nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
[ -n "$NFQWS2_MY1_UDP_PKT_IN" -a "$NFQWS2_MY1_UDP_PKT_IN" != 0 ] && {
|
||||
f4="udp sport {$NFQWS2_MY1_PORTS_UDP} $(nft_first_packets $NFQWS2_MY1_UDP_PKT_IN)"
|
||||
f6="$f4 ip6 saddr @$NFQWS2_MY1_NAME6"
|
||||
f4="$f4 ip saddr @$NFQWS2_MY1_NAME4"
|
||||
nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS2_MY1
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,6 +139,6 @@ zapret_custom_firewall_nft_flush()
|
||||
# this function is called after all nft fw rules are deleted
|
||||
# however sets are not deleted. it's desired to clear sets here.
|
||||
|
||||
nft_del_set $NFQWS_MY1_NAME4 2>/dev/null
|
||||
nft_del_set $NFQWS_MY1_NAME6 2>/dev/null
|
||||
nft_del_set $NFQWS2_MY1_NAME4 2>/dev/null
|
||||
nft_del_set $NFQWS2_MY1_NAME6 2>/dev/null
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_QUIC="${NFQWS_OPT_DESYNC_QUIC:---payload quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=2}"
|
||||
NFQWS_OPT_DESYNC_QUIC="${NFQWS_OPT_DESYNC_QUIC:---payload=quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=2}"
|
||||
|
||||
alloc_dnum DNUM_QUIC4ALL
|
||||
alloc_qnum QNUM_QUIC4ALL
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_STUN="${NFQWS_OPT_DESYNC_STUN:---payload stun --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
|
||||
NFQWS_OPT_DESYNC_STUN="${NFQWS_OPT_DESYNC_STUN:---payload=stun --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
|
||||
|
||||
alloc_dnum DNUM_STUN4ALL
|
||||
alloc_qnum QNUM_STUN4ALL
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
62
init.d/custom.d.examples.linux/80-dns-intercept
Normal file
62
init.d/custom.d.examples.linux/80-dns-intercept
Normal file
@@ -0,0 +1,62 @@
|
||||
# this custom script feeds dns response data to main nfqws2 instance
|
||||
# DISABLE_IPV{4,6} filters are not used intentionally. despite of not having wan ipv6 it's possible to query LAN DNS server over local ipv6
|
||||
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
local filt="-p udp --sport 53"
|
||||
local jump="-j NFQUEUE --queue-num $QNUM --queue-bypass"
|
||||
local rule chain lan lanifs
|
||||
|
||||
get_lanif lanifs
|
||||
|
||||
# router
|
||||
for lan in $lanifs; do
|
||||
rule="-o $lan $filt $jump"
|
||||
ipt_print_op $1 "$rule" "nfqws FORWARD (qnum $QNUM)"
|
||||
ipt_add_del $1 FORWARD -t mangle $rule
|
||||
ipt_print_op $1 "$rule" "nfqws FORWARD (qnum $QNUM)" 6
|
||||
ipt6_add_del $1 FORWARD -t mangle $rule
|
||||
done
|
||||
# dns client server
|
||||
for chain in INPUT OUTPUT ; do
|
||||
rule="$filt $jump"
|
||||
ipt_print_op $1 "$rule" "nfqws $chain (qnum $QNUM)"
|
||||
ipt_add_del $1 $chain -t mangle $rule
|
||||
ipt_print_op $1 "$rule" "nfqws $chain (qnum $QNUM)" 6
|
||||
ipt6_add_del $1 $chain -t mangle $rule
|
||||
done
|
||||
}
|
||||
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
# stop logic is not required
|
||||
|
||||
local rule="udp sport 53 queue num $QNUM bypass"
|
||||
|
||||
# router
|
||||
nft_print_op "oifname @lanif $rule" "nfqws forward (qnum $QNUM)" "4+6"
|
||||
nft_add_chain forward_dns_feed "type filter hook forward priority mangle;"
|
||||
nft_flush_chain forward_dns_feed
|
||||
nft_add_rule forward_dns_feed oifname @lanif $rule
|
||||
|
||||
# dns client
|
||||
nft_print_op "$rule" "nfqws input (qnum $QNUM)" "4+6"
|
||||
nft_add_chain input_dns_feed "type filter hook input priority mangle;"
|
||||
nft_flush_chain input_dns_feed
|
||||
nft_add_rule input_dns_feed $rule
|
||||
|
||||
# dns server
|
||||
nft_print_op "$rule" "nfqws output (qnum $QNUM)" "4+6"
|
||||
nft_add_chain output_dns_feed "type filter hook output priority mangle;"
|
||||
nft_flush_chain output_dns_feed
|
||||
nft_add_rule output_dns_feed $rule
|
||||
}
|
||||
|
||||
zapret_custom_firewall_nft_flush()
|
||||
{
|
||||
local chain
|
||||
for chain in forward_dns_feed input_dns_feed output_dns_feed; do
|
||||
nft_del_chain $chain 2>/dev/null
|
||||
done
|
||||
}
|
||||
145
init.d/custom.d.examples.linux/99-lan-filter
Normal file
145
init.d/custom.d.examples.linux/99-lan-filter
Normal file
@@ -0,0 +1,145 @@
|
||||
# this custom script sets FILTER_MARK to specified source ips
|
||||
|
||||
# NOTE !!! SCRIPT REQUIRES FILTER_MARK VAR IN CONFIG FILE !!!
|
||||
# NOTE !!! WITHOUT FILTER_MARK IT DOES NOTHING !!!
|
||||
|
||||
# NOTE !!! ON NON-OPENWRT SYSTEMS SCRIPT REQUIRES IFACE_LAN VAR IN CONFIG FILE !!!
|
||||
|
||||
# can override in config :
|
||||
# LAN ip/cidr list to be fooled. elements are space separated
|
||||
FILTER_LAN_IP="${FILTER_LAN_IP:-192.168.0.0/16}"
|
||||
FILTER_LAN_IP6="${FILTER_LAN_IP6:-fc00::/7}"
|
||||
# allow fooling from local system (0|1) ?
|
||||
FILTER_LAN_ALLOW_OUTPUT="${FILTER_LAN_ALLOW_OUTPUT:-1}"
|
||||
|
||||
FILTER_LAN_SET="lanfilter"
|
||||
FILTER_LAN_SET6="${FILTER_LAN_SET}6"
|
||||
FILTER_LAN_IPSET_SIZE=${FILTER_LAN_IPSET_SIZE:-256}
|
||||
FILTER_LAN_IPSET_OPT="${FILTER_LAN_IPSET_OPT:-hash:net hashsize 8192 maxelem $FILTER_LAN_IPSET_SIZE}"
|
||||
|
||||
filter_mark_check()
|
||||
{
|
||||
[ -n "$FILTER_MARK" ] || {
|
||||
echo "WARNING ! lan filter cannot work without FILTER_MARK set in config"
|
||||
return 1
|
||||
}
|
||||
[ "$DISABLE_IPV4" = 1 -a "$DISABLE_IPV6" = 1 ] && return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
filter_mark_check || return
|
||||
|
||||
local subnet lanifs rule
|
||||
local setmark="-j MARK --set-mark $FILTER_MARK/$FILTER_MARK"
|
||||
local filt4="-m set --match-set $FILTER_LAN_SET src"
|
||||
local filt6="-m set --match-set $FILTER_LAN_SET6 src"
|
||||
|
||||
get_lanif lanifs
|
||||
|
||||
[ "$DISABLE_IPV4" != 1 ] && {
|
||||
[ "$FILTER_LAN_ALLOW_OUTPUT" = 1 ] && {
|
||||
ipt_print_op $1 "$setmark" "filter output"
|
||||
ipt_add_del $1 OUTPUT -t mangle $setmark
|
||||
}
|
||||
[ -n "$lanifs" ] && {
|
||||
[ "$1" = 1 ] && {
|
||||
ipset create $FILTER_LAN_SET $FILTER_LAN_IPSET_OPT family inet 2>/dev/null
|
||||
ipset flush $FILTER_LAN_SET
|
||||
for subnet in $FILTER_LAN_IP; do
|
||||
echo add $FILTER_LAN_SET $subnet
|
||||
done | ipset -! restore
|
||||
}
|
||||
for lan in $lanifs; do
|
||||
rule="-i $lan $filt4 $setmark"
|
||||
ipt_print_op $1 "$rule" "filter forward"
|
||||
ipt_add_del $1 FORWARD -t mangle $rule
|
||||
done
|
||||
}
|
||||
}
|
||||
[ "$DISABLE_IPV6" != 1 ] && {
|
||||
[ "$FILTER_LAN_ALLOW_OUTPUT" = 1 ] && {
|
||||
ipt_print_op $1 "$setmark" "filter output" 6
|
||||
ipt6_add_del $1 OUTPUT -t mangle $setmark
|
||||
}
|
||||
[ -n "$lanifs" ] && {
|
||||
[ "$1" = 1 ] && {
|
||||
ipset create $FILTER_LAN_SET6 $FILTER_LAN_IPSET_OPT family inet6 2>/dev/null
|
||||
ipset flush $FILTER_LAN_SET6
|
||||
for subnet in $FILTER_LAN_IP6; do
|
||||
echo add $FILTER_LAN_SET6 $subnet
|
||||
done | ipset -! restore
|
||||
}
|
||||
for lan in $lanifs; do
|
||||
rule="-i $lan $filt6 $setmark"
|
||||
ipt_print_op $1 "$rule" "filter forward" 6
|
||||
ipt6_add_del $1 FORWARD -t mangle $rule
|
||||
done
|
||||
}
|
||||
}
|
||||
|
||||
[ "$1" = 1 ] || {
|
||||
ipset destroy $FILTER_LAN_SET 2>/dev/null
|
||||
ipset destroy $FILTER_LAN_SET6 2>/dev/null
|
||||
}
|
||||
}
|
||||
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
filter_mark_check || return
|
||||
|
||||
local subnets rule
|
||||
local setmark="meta mark set meta mark or $FILTER_MARK"
|
||||
local filt4="ip saddr == @$FILTER_LAN_SET"
|
||||
local filt6="ip6 saddr == @$FILTER_LAN_SET6"
|
||||
local lanif="iifname @lanif"
|
||||
|
||||
nft_add_chain forward_lan_filter "type filter hook forward priority mangle;"
|
||||
nft_flush_chain forward_lan_filter
|
||||
|
||||
if [ "$FILTER_LAN_ALLOW_OUTPUT" = 1 ]; then
|
||||
nft_add_chain output_lan_filter "type filter hook output priority mangle;"
|
||||
nft_flush_chain output_lan_filter
|
||||
nft_print_op "$setmark" "filter output" "4+6"
|
||||
nft_add_rule output_lan_filter $setmark
|
||||
else
|
||||
nft_del_chain output_lan_filter 2>/dev/null
|
||||
fi
|
||||
|
||||
[ "$DISABLE_IPV4" != 1 ] && {
|
||||
make_comma_list subnets $FILTER_LAN_IP
|
||||
nft_create_set $FILTER_LAN_SET "type ipv4_addr; size $FILTER_LAN_IPSET_SIZE; auto-merge; flags interval;"
|
||||
nft_flush_set $FILTER_LAN_SET
|
||||
nft_add_set_element $FILTER_LAN_SET "$subnets"
|
||||
|
||||
rule="$lanif $filt4 $setmark"
|
||||
nft_print_op "$rule" "filter forward" "4"
|
||||
nft_add_rule forward_lan_filter $rule
|
||||
}
|
||||
[ "$DISABLE_IPV6" != 1 ] && {
|
||||
make_comma_list subnets $FILTER_LAN_IP6
|
||||
nft_create_set $FILTER_LAN_SET6 "type ipv6_addr; size $FILTER_LAN_IPSET_SIZE; auto-merge; flags interval;"
|
||||
nft_flush_set $FILTER_LAN_SET6
|
||||
nft_add_set_element $FILTER_LAN_SET6 "$subnets"
|
||||
|
||||
rule="$lanif $filt6 $setmark"
|
||||
nft_print_op "$rule" "filter forward" "6"
|
||||
nft_add_rule forward_lan_filter $rule
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
zapret_custom_firewall_nft_flush()
|
||||
{
|
||||
# this function is called after all nft fw rules are deleted
|
||||
# however sets are not deleted. it's desired to clear sets here.
|
||||
|
||||
nft_del_chain forward_lan_filter 2>/dev/null
|
||||
nft_del_chain output_lan_filter 2>/dev/null
|
||||
|
||||
nft_del_set $FILTER_LAN_SET 2>/dev/null
|
||||
nft_del_set $FILTER_LAN_SET6 2>/dev/null
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -62,6 +62,20 @@ network_find_wanX_devices()
|
||||
call_for_multiple_items network_get_device $2 "$ifaces"
|
||||
}
|
||||
|
||||
get_wanif46()
|
||||
{
|
||||
# $1 - 4/6
|
||||
# $2 - var to receive interface list
|
||||
local ifaces
|
||||
network_find_wan${1}_all ifaces
|
||||
call_for_multiple_items network_get_device $2 "$ifaces"
|
||||
}
|
||||
get_lanif()
|
||||
{
|
||||
# $1 - var to receive interface list
|
||||
call_for_multiple_items network_get_device $1 "$OPENWRT_LAN"
|
||||
}
|
||||
|
||||
|
||||
fw_nfqws_prepost_x()
|
||||
{
|
||||
@@ -71,10 +85,8 @@ fw_nfqws_prepost_x()
|
||||
# $4 - 4/6
|
||||
# $5 - post/pre
|
||||
|
||||
local ifaces DWAN
|
||||
network_find_wan${4}_all ifaces
|
||||
call_for_multiple_items network_get_device DWAN "$ifaces"
|
||||
|
||||
local DWAN
|
||||
get_wanif46 $4 DWAN
|
||||
[ -n "$DWAN" ] && _fw_nfqws_${5}${4} $1 "$2" $3 "$(unique $DWAN)"
|
||||
}
|
||||
fw_nfqws_post4()
|
||||
|
||||
@@ -75,6 +75,26 @@ NFQWS2="${NFQWS2:-$ZAPRET_BASE/nfq2/nfqws2}"
|
||||
LUAOPT="--lua-init=@$ZAPRET_BASE/lua/zapret-lib.lua --lua-init=@$ZAPRET_BASE/lua/zapret-antidpi.lua --lua-init=@$ZAPRET_BASE/lua/zapret-auto.lua"
|
||||
NFQWS2_OPT_BASE="$USEROPT --fwmark=$DESYNC_MARK $LUAOPT"
|
||||
|
||||
get_wanif46()
|
||||
{
|
||||
# $1 - 4/6
|
||||
# $2 - var to receive interface list
|
||||
case $1 in
|
||||
6)
|
||||
eval $2="\${IFACE_WAN6:-$IFACE_WAN}"
|
||||
;;
|
||||
4)
|
||||
eval $2="\$IFACE_WAN"
|
||||
;;
|
||||
*)
|
||||
eval $2=
|
||||
esac
|
||||
}
|
||||
get_lanif()
|
||||
{
|
||||
# $1 - var to receive interface list
|
||||
eval $1="\$IFACE_LAN"
|
||||
}
|
||||
|
||||
fw_nfqws_post4()
|
||||
{
|
||||
@@ -119,7 +139,7 @@ nft_wanif6_filter_present()
|
||||
}
|
||||
nft_fill_ifsets_overload()
|
||||
{
|
||||
nft_fill_ifsets "$IFACE_WAN" "${IFACE_WAN6:-$IFACE_WAN}" "$IFACE_LAN"
|
||||
nft_fill_ifsets "$IFACE_LAN" "$IFACE_WAN" "${IFACE_WAN6:-$IFACE_WAN}"
|
||||
}
|
||||
|
||||
|
||||
|
||||
1
init.d/windivert.filter.examples/windivert_part.dht.txt
Normal file
1
init.d/windivert.filter.examples/windivert_part.dht.txt
Normal file
@@ -0,0 +1 @@
|
||||
udp.Length>=5 and udp.Payload[0]=0x64 and udp.Payload[1]>=0x31 and udp.Payload[1]<=0x32
|
||||
@@ -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
|
||||
@@ -1,3 +1,3 @@
|
||||
outbound and
|
||||
udp.PayloadLength=148 and
|
||||
udp.Payload[0]=0x01
|
||||
udp.PayloadLength=148 and udp.Payload32[0]=0x01000000 or
|
||||
udp.PayloadLength=92 and udp.Payload32[0]=0x02000000 or
|
||||
udp.PayloadLength=64 and udp.Payload32[0]=0x03000000
|
||||
|
||||
@@ -31,7 +31,7 @@ select_test_method()
|
||||
elif exists zsh && [ "$UNAME" != CYGWIN ] ; then
|
||||
TEST=zsh
|
||||
elif [ "$UNAME" != CYGWIN ]; then
|
||||
if exists hexdump and exists dd; then
|
||||
if exists hexdump && exists dd; then
|
||||
# macos does not use ELF
|
||||
TEST=elf
|
||||
ELF=
|
||||
@@ -157,7 +157,7 @@ fi
|
||||
unset PKTWS
|
||||
case $UNAME in
|
||||
Linux)
|
||||
ARCHLIST="my linux-x86_64 linux-x86 linux-arm64 linux-arm linux-mips64 linux-mipsel linux-mips linux-lexra linux-ppc"
|
||||
ARCHLIST="my linux-x86_64 linux-x86 linux-arm64 linux-arm linux-mips64 linux-mipsel64 linux-mipsel linux-mips linux-lexra linux-ppc linux-riscv64"
|
||||
PKTWS=nfqws2
|
||||
;;
|
||||
FreeBSD)
|
||||
|
||||
@@ -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
|
||||
@@ -288,7 +288,7 @@ ask_config_tmpdir()
|
||||
echo /tmp in openwrt is tmpfs. on low RAM systems there may be not enough RAM to store downloaded files
|
||||
echo default tmpfs has size of 50% RAM
|
||||
echo "RAM : $(get_ram_mb) Mb"
|
||||
echo "DISK : $(get_free_space_mb) Mb"
|
||||
echo "DISK : $(get_free_space_mb "$EXEDIR/tmp") Mb"
|
||||
echo select temp file location
|
||||
[ -z "$TMPDIR" ] && TMPDIR=/tmp
|
||||
ask_list TMPDIR "/tmp $EXEDIR/tmp" && {
|
||||
@@ -601,7 +601,7 @@ check_dns()
|
||||
|
||||
install_systemd()
|
||||
{
|
||||
INIT_SCRIPT_SRC="$EXEDIR/init.d/sysv/zapret"
|
||||
INIT_SCRIPT_SRC="$EXEDIR/init.d/sysv/zapret2"
|
||||
CUSTOM_DIR="$ZAPRET_RW/init.d/sysv"
|
||||
|
||||
check_bins
|
||||
|
||||
@@ -49,7 +49,7 @@ static int ucmp(const void * a, const void * b, void *arg)
|
||||
}
|
||||
static uint32_t mask_from_bitcount(uint32_t zct)
|
||||
{
|
||||
return zct<32 ? ~((1 << zct) - 1) : 0;
|
||||
return zct<32 ? ~((1u << zct) - 1) : 0;
|
||||
}
|
||||
// make presorted array unique. return number of unique items.
|
||||
// 1,1,2,3,3,0,0,0 (ct=8) => 1,2,3,0 (ct=4)
|
||||
@@ -138,7 +138,7 @@ static void mask_from_bitcount6_make(uint32_t zct, struct in6_addr *a)
|
||||
int32_t n = (127 - zct) >> 3;
|
||||
memset(a->s6_addr,0xFF,n);
|
||||
memset(a->s6_addr+n,0x00,16-n);
|
||||
a->s6_addr[n] = ~((1 << (zct & 7)) - 1);
|
||||
a->s6_addr[n] = ~((1u << (zct & 7)) - 1);
|
||||
}
|
||||
}
|
||||
static struct in6_addr ip6_mask[129];
|
||||
|
||||
@@ -68,7 +68,6 @@ ipset_restore()
|
||||
{
|
||||
# $1 - ipset name
|
||||
# $2 - filename
|
||||
|
||||
zzexist "$2" || return
|
||||
local fsize=$(zzsize "$2")
|
||||
local svram=0
|
||||
@@ -77,7 +76,7 @@ ipset_restore()
|
||||
|
||||
local T="Adding to ipset $1 "
|
||||
[ "$svram" = "1" ] && T="$T (saveram)"
|
||||
T="$T : $f"
|
||||
T="$T : $2"
|
||||
echo $T
|
||||
|
||||
if [ "$svram" = "1" ]; then
|
||||
|
||||
15
ipset/def.sh
15
ipset/def.sh
@@ -44,7 +44,9 @@ ZUSERLIST_EXCLUDE="$IPSET_RW_DIR/zapret-hosts-user-exclude.txt"
|
||||
|
||||
[ -n "$IP2NET" ] || IP2NET="$ZAPRET_BASE/ip2net/ip2net"
|
||||
[ -n "$MDIG" ] || MDIG="$ZAPRET_BASE/mdig/mdig"
|
||||
[ -z "$MDIG_THREADS" ] && MDIG_THREADS=30
|
||||
MDIG_THREADS=${MDIG_THREADS:-30}
|
||||
MDIG_EAGAIN=${MDIG_EAGAIN:-10}
|
||||
MDIG_EAGAIN_DELAY=${MDIG_EAGAIN_DELAY:-500}
|
||||
|
||||
|
||||
|
||||
@@ -124,7 +126,7 @@ zzcat()
|
||||
zz()
|
||||
{
|
||||
if [ "$GZIP_LISTS" = "1" ]; then
|
||||
gzip -c >"$1.gz"
|
||||
gzip -9c >"$1.gz"
|
||||
rm -f "$1"
|
||||
else
|
||||
cat >"$1"
|
||||
@@ -161,7 +163,7 @@ digger()
|
||||
if [ -x "$MDIG" ]; then
|
||||
local cmd
|
||||
[ "$2" = "s" ] && cmd=--stats=1000
|
||||
"$MDIG" --family=$1 --threads=$MDIG_THREADS $cmd
|
||||
"$MDIG" --family=$1 --threads=$MDIG_THREADS --eagain=$MDIG_EAGAIN --eagain-delay=$MDIG_EAGAIN_DELAY $cmd
|
||||
else
|
||||
local A=A
|
||||
[ "$1" = "6" ] && A=AAAA
|
||||
@@ -272,11 +274,10 @@ hup_zapret_daemons()
|
||||
{
|
||||
echo forcing zapret daemons to reload their hostlist
|
||||
if exists killall; then
|
||||
killall -HUP tpws nfqws dvtws 2>/dev/null
|
||||
killall -HUP nfqws2 dvtws2 2>/dev/null
|
||||
elif exists pkill; then
|
||||
pkill -HUP ^tpws$
|
||||
pkill -HUP ^nfqws$
|
||||
pkill -HUP ^dvtws$
|
||||
pkill -HUP ^nfqws2$
|
||||
pkill -HUP ^dvtws2$
|
||||
else
|
||||
echo no mass killer available ! cant HUP zapret daemons
|
||||
fi
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
@@ -38,6 +38,7 @@ standard fooling :
|
||||
* tcp_flags_set=<list> - set tcp flags in comma separated list
|
||||
* tcp_flags_unset=<list> - unset tcp flags in comma separated list
|
||||
* tcp_ts_up - move timestamp tcp option to the top if present (workaround for badack without badseq fooling)
|
||||
* tcp_nop_del - delete NOP tcp options to free space in tcp header
|
||||
|
||||
* fool=fool_function - custom fooling function : fool_func(dis, fooling_options)
|
||||
|
||||
@@ -53,7 +54,7 @@ standard rawsend :
|
||||
|
||||
standard payload :
|
||||
|
||||
* payload - comma separarated list of allowed payload types. if not present - allow non-empty known payloads.
|
||||
* payload - comma separated list of allowed payload types. if not present - allow non-empty known payloads.
|
||||
|
||||
standard ip_id :
|
||||
|
||||
@@ -64,8 +65,10 @@ standard ipfrag :
|
||||
|
||||
* ipfrag[=frag_function] - ipfrag function name. "ipfrag2" by default if empty
|
||||
* ipfrag_disorder - send fragments from last to first
|
||||
* ipfrag2 : ipfrag_pos_udp - udp frag position. ipv4 : starting from L4 header. ipb6: starting from fragmentable part. must be multiple of 8. default 8
|
||||
* ipfrag2 : ipfrag_pos_tcp - tcp frag position. ipv4 : starting from L4 header. ipb6: starting from fragmentable part. must be multiple of 8. default 32
|
||||
* ipfrag2 : ipfrag_pos_tcp - tcp frag position. ipv4 : starting from L4 header. ipv6: starting from fragmentable part. must be multiple of 8. default 32
|
||||
* ipfrag2 : ipfrag_pos_udp - udp frag position. ipv4 : starting from L4 header. ipv6: starting from fragmentable part. must be multiple of 8. default 8
|
||||
* ipfrag2 : ipfrag_pos_icmp - icmp frag position. ipv4 : starting from L4 header. ipv6: starting from fragmentable part. must be multiple of 8. default 8
|
||||
* ipfrag2 : ipfrag_pos - frag position for other L4. ipv4 : starting from L4 header. ipv6: starting from fragmentable part. must be multiple of 8. default 32
|
||||
* ipfrag2 : ipfrag_next - next protocol field in ipv6 fragment extenstion header of the second fragment. same as first by default.
|
||||
|
||||
]]
|
||||
@@ -113,7 +116,8 @@ end
|
||||
-- standard args : direction
|
||||
function http_domcase(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -139,7 +143,8 @@ end
|
||||
-- arg : spell=<str> . spelling of the "Host" header. must be exactly 4 chars long
|
||||
function http_hostcase(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -149,12 +154,17 @@ function http_hostcase(ctx, desync)
|
||||
error("http_hostcase: invalid host spelling '"..spell.."'")
|
||||
else
|
||||
local hdis = http_dissect_req(desync.dis.payload)
|
||||
if hdis.headers.host then
|
||||
DLOG("http_hostcase: 'Host:' => '"..spell.."'")
|
||||
desync.dis.payload = string.sub(desync.dis.payload,1,hdis.headers.host.pos_start-1)..spell..string.sub(desync.dis.payload,hdis.headers.host.pos_header_end+1)
|
||||
return VERDICT_MODIFY
|
||||
if hdis then
|
||||
local idx_host = array_field_search(hdis.headers, "header_low", "host")
|
||||
if idx_host then
|
||||
DLOG("http_hostcase: 'Host:' => '"..spell.."'")
|
||||
desync.dis.payload = string.sub(desync.dis.payload,1,hdis.headers[idx_host].pos_start-1)..spell..string.sub(desync.dis.payload,hdis.headers[idx_host].pos_header_end+1)
|
||||
return VERDICT_MODIFY
|
||||
else
|
||||
DLOG("http_hostcase: 'Host:' header not found")
|
||||
end
|
||||
else
|
||||
DLOG("http_hostcase: 'Host:' header not found")
|
||||
DLOG("http_hostcase: http dissect error")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -162,25 +172,68 @@ end
|
||||
|
||||
-- nfqws1 : "--methodeol"
|
||||
-- standard args : direction
|
||||
-- NOTE : if using with other http tampering methodeol should be the last !
|
||||
function http_methodeol(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
if desync.l7payload=="http_req" and direction_check(desync) then
|
||||
local hdis = http_dissect_req(desync.dis.payload)
|
||||
local ua = hdis.headers["user-agent"]
|
||||
if ua then
|
||||
if (ua.pos_end - ua.pos_value_start) < 2 then
|
||||
DLOG("http_methodeol: 'User-Agent:' header is too short")
|
||||
if hdis then
|
||||
local idx_ua = array_field_search(hdis.headers, "header_low", "user-agent")
|
||||
if idx_ua then
|
||||
local ua = hdis.headers[idx_ua]
|
||||
if (ua.pos_end - ua.pos_value_start) < 2 then
|
||||
DLOG("http_methodeol: 'User-Agent:' header is too short")
|
||||
else
|
||||
DLOG("http_methodeol: applied")
|
||||
desync.dis.payload="\r\n"..string.sub(desync.dis.payload,1,ua.pos_end-2)..(string.sub(desync.dis.payload,ua.pos_end+1) or "");
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
else
|
||||
DLOG("http_methodeol: applied")
|
||||
desync.dis.payload="\r\n"..string.sub(desync.dis.payload,1,ua.pos_end-2)..(string.sub(desync.dis.payload,ua.pos_end+1) or "");
|
||||
return VERDICT_MODIFY
|
||||
DLOG("http_methodeol: 'User-Agent:' header not found")
|
||||
end
|
||||
else
|
||||
DLOG("http_methodeol: 'User-Agent:' header not found")
|
||||
DLOG("http_methodeol: http dissect error")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- nfqws1 : not available
|
||||
-- tpws : --unixeol
|
||||
-- standard args : direction
|
||||
function http_unixeol(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
if desync.l7payload=="http_req" and direction_check(desync) then
|
||||
local hdis = http_dissect_req(desync.dis.payload)
|
||||
if hdis then
|
||||
local idx_ua = array_field_search(hdis.headers, "header_low", "user-agent")
|
||||
if idx_ua then
|
||||
local http = http_reconstruct_req(hdis, true)
|
||||
if #http < #desync.dis.payload then
|
||||
hdis.headers[idx_ua].value = hdis.headers[idx_ua].value .. string.rep(" ", #desync.dis.payload - #http)
|
||||
end
|
||||
local http = http_reconstruct_req(hdis, true)
|
||||
if #http==#desync.dis.payload then
|
||||
desync.dis.payload = http
|
||||
DLOG("http_unixeol: applied")
|
||||
return VERDICT_MODIFY
|
||||
else
|
||||
DLOG("http_unixeol: reconstruct differs in size from original: "..#http.."!="..#desync.dis.payload)
|
||||
end
|
||||
else
|
||||
DLOG("http_unixeol: 'User-Agent:' header absent")
|
||||
end
|
||||
else
|
||||
DLOG("http_unixeol: could not dissect http")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -224,7 +277,8 @@ function synack_split(ctx, desync)
|
||||
instance_cutoff_shim(ctx, desync) -- mission complete
|
||||
end
|
||||
else
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -241,7 +295,8 @@ function synack(ctx, desync)
|
||||
instance_cutoff_shim(ctx, desync) -- mission complete
|
||||
end
|
||||
else
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -259,7 +314,8 @@ function wsize(ctx, desync)
|
||||
instance_cutoff_shim(ctx, desync) -- mission complete
|
||||
end
|
||||
else
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -270,7 +326,8 @@ end
|
||||
-- arg : forced_cutoff=<list> - comma separated list of payloads that trigger forced wssize cutoff. by default - any non-empty payload
|
||||
function wssize(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
local verdict = VERDICT_PASS
|
||||
@@ -287,6 +344,40 @@ 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
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
if direction_check(desync) then
|
||||
if not desync.arg.blob then
|
||||
error("tls_client_hello_clone: 'blob' arg required")
|
||||
end
|
||||
if desync.l7payload=="tls_client_hello" then
|
||||
desync[desync.arg.blob] = tls_client_hello_mod(desync.reasm_data or desync.dis.payload, desync.arg)
|
||||
if desync[desync.arg.blob] then
|
||||
DLOG("tls_client_hello_clone: cloned to desync."..desync.arg.blob)
|
||||
end
|
||||
end
|
||||
if not desync[desync.arg.blob] and desync.arg.fallback then
|
||||
DLOG("tls_client_hello_clone: desync."..desync.arg.blob.."="..desync.arg.fallback)
|
||||
desync[desync.arg.blob] = blob(desync, desync.arg.fallback)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- nfqws1 : "--dpi-desync=syndata"
|
||||
-- standard args : fooling, rawsend, reconstruct, ipfrag
|
||||
-- arg : blob=<blob> - fake payload. must fit to single packet. no segmentation possible. default - 16 zero bytes.
|
||||
@@ -308,7 +399,8 @@ function syndata(ctx, desync)
|
||||
instance_cutoff_shim(ctx, desync) -- mission complete
|
||||
end
|
||||
else
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -317,7 +409,8 @@ end
|
||||
-- arg : rstack - send RST,ACK instead of RST
|
||||
function rst(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -340,15 +433,20 @@ 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)
|
||||
-- by default process only outgoing known payloads
|
||||
if direction_check(desync) and payload_check(desync) then
|
||||
-- by default process only outgoing known payloads. works only for tcp and udp
|
||||
if (desync.dis.tcp or desync.dis.udp) and direction_check(desync) and payload_check(desync) then
|
||||
if replay_first(desync) then
|
||||
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,14 +466,19 @@ 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
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
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 +496,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,20 +526,73 @@ function multisplit(ctx, desync)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function pos_normalize(pos, low, hi)
|
||||
return (pos>=low and pos<hi) and (pos-low+1) or nil
|
||||
end
|
||||
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
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
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 +603,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 +628,61 @@ 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
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
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,14 +690,19 @@ 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
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
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
|
||||
@@ -522,14 +729,15 @@ function hostfakesplit(ctx, desync)
|
||||
local midhost
|
||||
if desync.arg.midhost then
|
||||
midhost = resolve_pos(data,desync.l7payload,desync.arg.midhost)
|
||||
if not midhost then
|
||||
if midhost then
|
||||
DLOG("hosfakesplit: midhost marker resolved to "..midhost)
|
||||
if midhost<=pos[1] or midhost>pos[2] then
|
||||
DLOG("hostfakesplit: midhost is not inside the host range")
|
||||
midhost = nil
|
||||
end
|
||||
else
|
||||
DLOG("hostfakesplit: cannot resolve midhost marker '"..desync.arg.midhost.."'")
|
||||
end
|
||||
DLOG("hosfakesplit: midhost marker resolved to "..midhost)
|
||||
if midhost<=pos[1] or midhost>pos[2] then
|
||||
DLOG("hostfakesplit: midhost is not inside the host range")
|
||||
midhost = nil
|
||||
end
|
||||
end
|
||||
-- if present apply ipfrag only to real host parts. fakes and parts outside of the host must be visible to DPI.
|
||||
if midhost then
|
||||
@@ -601,14 +809,19 @@ 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
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
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 +829,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 +853,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,14 +914,19 @@ 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
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
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 +934,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
|
||||
|
||||
@@ -718,7 +943,7 @@ function fakeddisorder(ctx, desync)
|
||||
local opts_orig = {rawsend = rawsend_opts_base(desync), reconstruct = {}, ipfrag = {}, ipid = desync.arg, fooling = {tcp_ts_up = desync.arg.tcp_ts_up}}
|
||||
local opts_fake = {rawsend = rawsend_opts(desync), reconstruct = reconstruct_opts(desync), ipfrag = {}, ipid = desync.arg, fooling = desync.arg}
|
||||
|
||||
fakepat = desync.arg.pattern and blob(desync,desync.arg.pattern) or "\x00"
|
||||
local fakepat = desync.arg.pattern and blob(desync,desync.arg.pattern) or "\x00"
|
||||
|
||||
-- second fake
|
||||
fake = pattern(fakepat,pos,#data-pos+1)
|
||||
@@ -738,7 +963,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,16 +1027,21 @@ 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)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(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 +1055,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
|
||||
@@ -832,6 +1076,106 @@ function tcpseg(ctx, desync)
|
||||
end
|
||||
end
|
||||
|
||||
-- nfqws1 : not available
|
||||
-- tpws : close analog is "--split-pos=.. --oob" but works not the same way
|
||||
-- standard args : fooling, ip_id, rawsend, reconstruct, ipfrag
|
||||
-- arg : char - oob char
|
||||
-- arg : byte - oob byte
|
||||
-- arg : urp - urgent pointer position marker, 'b' or 'e'. default - 0
|
||||
function oob(ctx, desync)
|
||||
if not desync.track then return end
|
||||
if not desync.dis.tcp then
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
local key = desync.func_instance.."_syn"
|
||||
if not desync.track.lua_state[key] then
|
||||
if bitand(desync.dis.tcp.th_flags, TH_SYN+TH_ACK)~=TH_SYN then
|
||||
DLOG("oob: must be applied since the very beginning of the tcp connection - SYN packet")
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
desync.track.lua_state[key] = true
|
||||
end
|
||||
if desync.outgoing then
|
||||
-- direct pos - outgoing
|
||||
local pos = pos_get(desync, 's', false)
|
||||
if pos<=1 then
|
||||
local dseq = u32add(desync.dis.tcp.th_seq, -1)
|
||||
DLOG("oob: decreasing outgoing seq : "..desync.dis.tcp.th_seq.." => "..dseq)
|
||||
desync.dis.tcp.th_seq = dseq
|
||||
end
|
||||
if pos==0 then
|
||||
return VERDICT_MODIFY
|
||||
elseif pos==1 then
|
||||
local data = desync.reasm_data or desync.dis.payload
|
||||
if #data==0 then
|
||||
-- empty ACK
|
||||
return VERDICT_MODIFY
|
||||
else
|
||||
local oob = desync.arg.char or (desync.arg.byte and bu8(desync.arg.byte) or nil) or "\x00"
|
||||
if #oob~=1 then
|
||||
error("oob: OOB must be exactly one byte")
|
||||
end
|
||||
local dis_oob = deepcopy(desync.dis)
|
||||
local urp
|
||||
if not desync.arg.urp or desync.arg.urp=='b' then
|
||||
urp = 1
|
||||
dis_oob.tcp.th_urp = 0
|
||||
elseif desync.arg.urp=='e' then
|
||||
urp = #data+1
|
||||
dis_oob.tcp.th_urp = urp
|
||||
else
|
||||
urp = resolve_pos(data, desync.l7payload, desync.arg.urp)
|
||||
if not urp then
|
||||
DLOG("oob: cannot resolve urp marker '"..desync.arg.urp.."'")
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
DLOG("oob: resolved urp marker to "..urp-1)
|
||||
dis_oob.tcp.th_urp = urp
|
||||
end
|
||||
DLOG("oob: th_urp "..dis_oob.tcp.th_urp)
|
||||
-- one byte OOB payload
|
||||
dis_oob.payload = string.sub(data, 1, urp-1) .. oob .. string.sub(data, urp)
|
||||
dis_oob.tcp.th_flags = bitor(dis_oob.tcp.th_flags, TH_URG)
|
||||
DLOG("oob: sending OOB")
|
||||
if not rawsend_dissect_segmented(desync, dis_oob) then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
if not desync.replay then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
end
|
||||
return VERDICT_DROP
|
||||
else
|
||||
-- drop replay and cutoff
|
||||
if desync.replay then
|
||||
DLOG("oob: dropping replay piece")
|
||||
if desync.replay_piece_last then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
return VERDICT_DROP
|
||||
end
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
else
|
||||
-- reverse pos - outgoing
|
||||
local pos = pos_get(desync, 's', true)
|
||||
if pos>1 then
|
||||
DLOG("oob: unexpected outgoing position "..pos)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
local dack = u32add(desync.dis.tcp.th_ack, 1)
|
||||
DLOG("oob: increasing incoming ack : "..desync.dis.tcp.th_ack.." => "..dack)
|
||||
desync.dis.tcp.th_ack = dack
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
end
|
||||
|
||||
-- nfqws1 : "--dpi-desync=udplen"
|
||||
-- standard args : direction, payload
|
||||
-- arg : min=N . do not act on payloads smaller than N bytes
|
||||
@@ -841,7 +1185,8 @@ end
|
||||
-- arg : pattern_offset=N . offset in the pattern. 0 by default
|
||||
function udplen(ctx, desync)
|
||||
if not desync.dis.udp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -874,15 +1219,16 @@ 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)
|
||||
-- do not cutoff on related icmp
|
||||
if not desync.dis.icmp then instance_cutoff_shim(ctx, desync) end
|
||||
return
|
||||
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)
|
||||
|
||||
@@ -1,20 +1,48 @@
|
||||
-- standard automation/orchestration code
|
||||
-- this is related to making dynamic strategy decisions without rewriting or altering strategy function code
|
||||
-- orchestrators can decide which instances to call or not to call or pass them dynamic arguments
|
||||
-- failure detectors test potential block conditions for orchestrators
|
||||
-- failure and success detectors test potential block conditions for orchestrators
|
||||
|
||||
-- standard host key generator for per-host storage
|
||||
-- arg: reqhost - require hostname, do not work with ip
|
||||
-- arg: key - a string - table name inside autostate table. to allow multiple orchestrator instances to use single host storage
|
||||
function automate_host_record(desync)
|
||||
local hostkey, askey
|
||||
if desync.arg.reqhost then
|
||||
hostkey = desync.track and desync.track.hostname
|
||||
else
|
||||
hostkey = host_or_ip(desync)
|
||||
-- arg: nld=N - cut hostname to N level domain. NLD=2 static.intranet.microsoft.com => microsoft.com
|
||||
function standard_hostkey(desync)
|
||||
local hostkey = desync.track and desync.track.hostname
|
||||
if hostkey then
|
||||
if desync.arg.nld and tonumber(desync.arg.nld)>0 and not (desync.track and desync.track.hostname_is_ip) then
|
||||
-- dissect_nld returns nil if domain is invalid or does not have this NLD
|
||||
-- fall back to original hostkey if it fails
|
||||
local hktemp = dissect_nld(hostkey, tonumber(desync.arg.nld))
|
||||
if hktemp then
|
||||
hostkey = hktemp
|
||||
end
|
||||
end
|
||||
elseif not desync.arg.reqhost then
|
||||
hostkey = host_ip(desync)
|
||||
end
|
||||
return hostkey
|
||||
end
|
||||
|
||||
-- per-host storage
|
||||
-- arg: key - a string - table name inside autostate table. to allow multiple orchestrator instances to use single host storage
|
||||
-- arg: hostkey - hostkey generator function name
|
||||
function automate_host_record(desync)
|
||||
local hostkey, hkf, askey
|
||||
|
||||
if desync.arg.hostkey then
|
||||
if type(_G[desync.arg.hostkey])~="function" then
|
||||
error("automate: invalid hostkey function '"..desync.arg.hostkey.."'")
|
||||
end
|
||||
hkf = _G[desync.arg.hostkey]
|
||||
else
|
||||
hkf = standard_hostkey
|
||||
end
|
||||
hostkey = hkf(desync)
|
||||
if not hostkey then
|
||||
DLOG("automate: host record key unavailable")
|
||||
return nil
|
||||
end
|
||||
|
||||
askey = (desync.arg.key and #desync.arg.key>0) and desync.arg.key or desync.func_instance
|
||||
DLOG("automate: host record key 'autostate."..askey.."."..hostkey.."'")
|
||||
if not autostate then
|
||||
@@ -28,7 +56,9 @@ function automate_host_record(desync)
|
||||
end
|
||||
return autostate[askey][hostkey]
|
||||
end
|
||||
-- per-connection storage
|
||||
function automate_conn_record(desync)
|
||||
if not desync.track then return nil end
|
||||
if not desync.track.lua_state.automate then
|
||||
desync.track.lua_state.automate = {}
|
||||
end
|
||||
@@ -65,19 +95,39 @@ 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
|
||||
function is_dpi_redirect(hostname, location)
|
||||
local ds = dissect_url(location)
|
||||
if ds.domain then
|
||||
if ds and ds.domain then
|
||||
local sld1 = dissect_nld(hostname,2)
|
||||
local sld2 = dissect_nld(ds.domain,2)
|
||||
return sld2 and sld1~=sld2
|
||||
return sld2 and sld1~=sld2 and true or false
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function standard_detector_defaults(arg)
|
||||
return {
|
||||
inseq = tonumber(arg.inseq) or 4096,
|
||||
retrans = tonumber(arg.retrans) or 3,
|
||||
maxseq = tonumber(arg.maxseq) or 32768,
|
||||
udp_in = tonumber(arg.udp_in) or 1,
|
||||
udp_out = tonumber(arg.udp_out) or 4,
|
||||
no_http_redirect = arg.no_http_redirect,
|
||||
no_rst = arg.no_rst,
|
||||
reset = arg.reset
|
||||
}
|
||||
end
|
||||
|
||||
-- standard failure detector
|
||||
-- works with tcp and udp
|
||||
-- detected failures:
|
||||
@@ -85,57 +135,62 @@ end
|
||||
-- incoming http redirection
|
||||
-- outgoing retransmissions
|
||||
-- udp too much out with too few in
|
||||
-- arg: seq=<rseq> - tcp: if packet is beyond this relative sequence number treat this connection as successful. default is 64K
|
||||
-- arg: maxseq=<rseq> - tcp: test retransmissions only within this relative sequence. default is 32K
|
||||
-- arg: retrans=N - tcp: retrans count threshold. default is 3
|
||||
-- arg: rst=<rseq> - tcp: maximum relative sequence number to treat incoming RST as DPI reset. default is 1
|
||||
-- arg: reset - send RST to retransmitter to break long wait
|
||||
-- arg: inseq=<rseq> - tcp: maximum relative sequence number to treat incoming RST as DPI reset. default is 4K
|
||||
-- arg: no_http_redirect - tcp: disable http_reply dpi redirect trigger
|
||||
-- arg: no_rst - tcp: disable incoming RST trigger
|
||||
-- arg: udp_out - udp: >= outgoing udp packets. default is 4
|
||||
-- arg: udp_in - udp: with <= incoming udp packets. default is 1
|
||||
function standard_failure_detector(desync, crec, arg)
|
||||
if crec.nocheck then return false end
|
||||
|
||||
local seq_rst = tonumber(arg.rst) or 1
|
||||
local retrans = tonumber(arg.retrans) or 3
|
||||
local maxseq = tonumber(arg.seq) or 0x10000
|
||||
local udp_in = tonumber(arg.udp_in) or 1
|
||||
local udp_out = tonumber(arg.udp_out) or 4
|
||||
|
||||
function standard_failure_detector(desync, crec)
|
||||
local arg = standard_detector_defaults(desync.arg)
|
||||
local trigger = false
|
||||
if desync.dis.tcp then
|
||||
local seq = pos_get(desync,'s')
|
||||
if maxseq and seq>maxseq then
|
||||
DLOG("standard_failure_detector: s"..seq.." is beyond s"..maxseq..". treating connection as successful")
|
||||
crec.nocheck = true
|
||||
return false
|
||||
end
|
||||
|
||||
if desync.outgoing then
|
||||
if #desync.dis.payload>0 and retrans and (crec.retrans or 0)<retrans then
|
||||
if #desync.dis.payload>0 and arg.retrans and arg.maxseq>0 and seq<=arg.maxseq and (crec.retrans or 0)<arg.retrans then
|
||||
if is_retransmission(desync) then
|
||||
crec.retrans = crec.retrans and (crec.retrans+1) or 1
|
||||
DLOG("standard_failure_detector: retransmission "..crec.retrans.."/"..retrans)
|
||||
trigger = crec.retrans>=retrans
|
||||
DLOG("standard_failure_detector: retransmission "..crec.retrans.."/"..arg.retrans)
|
||||
trigger = crec.retrans>=arg.retrans
|
||||
if trigger and arg.reset then
|
||||
local dis = deepcopy(desync.dis)
|
||||
dis.payload = nil
|
||||
dis_reverse(dis)
|
||||
dis.tcp.th_flags = TH_RST
|
||||
dis.tcp.th_win = desync.track and desync.track.pos.reverse.tcp.winsize or 64
|
||||
dis.tcp.options = nil
|
||||
if dis.ip6 then
|
||||
dis.ip6.ip6_flow = (desync.track and desync.track.pos.reverse.ip6_flow) and desync.track.pos.reverse.ip6_flow or 0x60000000;
|
||||
end
|
||||
DLOG("standard_failure_detector: sending RST to retransmitter")
|
||||
rawsend_dissect(dis, {ifout = desync.ifin})
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if seq_rst and bitand(desync.dis.tcp.th_flags, TH_RST)~=0 then
|
||||
trigger = seq<=seq_rst
|
||||
if not arg.no_rst and arg.inseq>0 and bitand(desync.dis.tcp.th_flags, TH_RST)~=0 and seq>=1 then
|
||||
trigger = seq<=arg.inseq
|
||||
if b_debug then
|
||||
if trigger then
|
||||
DLOG("standard_failure_detector: incoming RST s"..seq.." in range s"..seq_rst)
|
||||
DLOG("standard_failure_detector: incoming RST s"..seq.." in range s"..arg.inseq)
|
||||
else
|
||||
DLOG("standard_failure_detector: not counting incoming RST s"..seq.." beyond s"..seq_rst)
|
||||
DLOG("standard_failure_detector: not counting incoming RST s"..seq.." beyond s"..arg.inseq)
|
||||
end
|
||||
end
|
||||
elseif not arg.no_http_redirect and desync.l7payload=="http_reply" and desync.track.hostname then
|
||||
local hdis = http_dissect_reply(desync.dis.payload)
|
||||
if hdis and (hdis.code==302 or hdis.code==307) and hdis.headers.location and hdis.headers.location then
|
||||
trigger = is_dpi_redirect(desync.track.hostname, hdis.headers.location.value)
|
||||
if b_debug then
|
||||
if trigger then
|
||||
DLOG("standard_failure_detector: http redirect "..hdis.code.." to '"..hdis.headers.location.value.."'. looks like DPI redirect.")
|
||||
else
|
||||
DLOG("standard_failure_detector: http redirect "..hdis.code.." to '"..hdis.headers.location.value.."'. NOT a DPI redirect.")
|
||||
if hdis and (hdis.code==302 or hdis.code==307) then
|
||||
local idx_loc = array_field_search(hdis.headers, "header_low", "location")
|
||||
if idx_loc then
|
||||
trigger = is_dpi_redirect(desync.track.hostname, hdis.headers[idx_loc].value)
|
||||
if b_debug then
|
||||
if trigger then
|
||||
DLOG("standard_failure_detector: http redirect "..hdis.code.." to '"..hdis.headers[idx_loc].value.."'. looks like DPI redirect.")
|
||||
else
|
||||
DLOG("standard_failure_detector: http redirect "..hdis.code.." to '"..hdis.headers[idx_loc].value.."'. NOT a DPI redirect.")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -143,13 +198,13 @@ function standard_failure_detector(desync, crec, arg)
|
||||
end
|
||||
elseif desync.dis.udp then
|
||||
if desync.outgoing then
|
||||
if udp_out then
|
||||
local udp_in = udp_in or 0
|
||||
trigger = desync.track.pos.direct.pcounter>=udp_out and desync.track.pos.reverse.pcounter<=udp_in
|
||||
if arg.udp_out>0 then
|
||||
local pos_out = pos_get(desync,'n',false)
|
||||
local pos_in = pos_get(desync,'n',true)
|
||||
trigger = pos_out>=arg.udp_out and pos_in<=arg.udp_in
|
||||
if trigger then
|
||||
crec.nocheck = true
|
||||
if b_debug then
|
||||
DLOG("standard_failure_detector: udp_out "..desync.track.pos.direct.pcounter..">="..udp_out.." udp_in "..desync.track.pos.reverse.pcounter.."<="..udp_in)
|
||||
DLOG("standard_failure_detector: arg.udp_out "..pos_out..">="..arg.udp_out.." arg.udp_in "..pos_in.."<="..arg.udp_in)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -158,17 +213,102 @@ function standard_failure_detector(desync, crec, arg)
|
||||
return trigger
|
||||
end
|
||||
|
||||
-- standard success detector
|
||||
-- success means previous failures were temporary and counter should be reset
|
||||
-- detected successes:
|
||||
-- tcp: outgoing seq is beyond 'maxseq' and maxseq>0
|
||||
-- tcp: incoming seq is beyond 'inseq' and inseq>0
|
||||
-- udp: incoming packets count > `udp_in` and `udp_out`>0
|
||||
-- arg: maxseq=<rseq> - tcp: success if outgoing relative sequence is beyond this value. default is 32K
|
||||
-- arg: inseq=<rseq> - tcp: success if incoming relative sequence is beyond this value. default is 4K
|
||||
-- arg: udp_out - udp : must be nil or >0 to test udp_in
|
||||
-- arg: udp_in - udp: if number if incoming packets > udp_in it means success
|
||||
function standard_success_detector(desync, crec)
|
||||
local arg = standard_detector_defaults(desync.arg)
|
||||
if desync.dis.tcp then
|
||||
local seq = pos_get(desync,'s')
|
||||
if desync.outgoing then
|
||||
if arg.maxseq>0 and seq>arg.maxseq then
|
||||
DLOG("standard_success_detector: outgoing s"..seq.." is beyond s"..arg.maxseq..". treating connection as successful")
|
||||
return true
|
||||
end
|
||||
else
|
||||
if arg.inseq>0 and seq>arg.inseq then
|
||||
DLOG("standard_success_detector: incoming s"..seq.." is beyond s"..arg.inseq..". treating connection as successful")
|
||||
return true
|
||||
end
|
||||
end
|
||||
elseif desync.dis.udp then
|
||||
if not desync.outgoing then
|
||||
local pos = pos_get(desync,'n')
|
||||
if arg.udp_out>0 and pos>arg.udp_in then
|
||||
if b_debug then
|
||||
DLOG("standard_success_detector: arg.udp_in "..pos..">"..arg.udp_in)
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- calls success and failure detectors
|
||||
-- resets counter if success is detected
|
||||
-- increases counter if failure is detected
|
||||
-- returns true if failure counter exceeds threshold
|
||||
function automate_failure_check(desync, hrec, crec)
|
||||
if crec.nocheck then return false end
|
||||
|
||||
local failure_detector, success_detector
|
||||
if desync.arg.failure_detector then
|
||||
if type(_G[desync.arg.failure_detector])~="function" then
|
||||
error("automate: invalid failure detector function '"..desync.arg.failure_detector.."'")
|
||||
end
|
||||
failure_detector = _G[desync.arg.failure_detector]
|
||||
else
|
||||
failure_detector = standard_failure_detector
|
||||
end
|
||||
if desync.arg.success_detector then
|
||||
if type(_G[desync.arg.success_detector])~="function" then
|
||||
error("automate: invalid success detector function '"..desync.arg.success_detector.."'")
|
||||
end
|
||||
success_detector = _G[desync.arg.success_detector]
|
||||
else
|
||||
success_detector = standard_success_detector
|
||||
end
|
||||
|
||||
if success_detector(desync, crec) then
|
||||
crec.nocheck = true
|
||||
DLOG("automate: success detected")
|
||||
automate_failure_counter_reset(hrec)
|
||||
return false
|
||||
end
|
||||
if failure_detector(desync, crec) then
|
||||
crec.nocheck = true
|
||||
DLOG("automate: failure detected")
|
||||
local fails = tonumber(desync.arg.fails) or 3
|
||||
local maxtime = tonumber(desync.arg.time) or 60
|
||||
return automate_failure_counter(hrec, crec, fails, maxtime)
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
-- circularily change strategy numbers when failure count reaches threshold ('fails')
|
||||
-- works with tcp only
|
||||
-- this orchestrator requires redirection of incoming traffic to cache RST and http replies !
|
||||
-- each orchestrated instance must have strategy=N arg, where N starts from 1 and increment without gaps
|
||||
-- if 'final' arg is present in an orchestrated instance it stops rotation
|
||||
-- arg: fails=N - failture count threshold. default is 3
|
||||
-- arg: time=<sec> - if last failure happened earlier than `maxtime` seconds ago - reset failure counter. default is 60.
|
||||
-- arg: reqhost - pass with no tampering if hostname is unavailable
|
||||
-- arg: detector - failure detector function name.
|
||||
-- arg: success_detector - success detector function name
|
||||
-- arg: failure_detector - failure detector function name
|
||||
-- arg: hostkey - hostkey generator function name
|
||||
-- args for failure detector - see standard_failure_detector or your own detector
|
||||
-- test case: nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-auto.lua --in-range=-s1 --lua-desync=circular --lua-desync=argdebug:strategy=1 --lua-desync=argdebug:strategy=2
|
||||
-- args for success detector - see standard_success_detector or your own detector
|
||||
-- args for hostkey generator - see standard_hostkey or your own generator
|
||||
-- test case: --in-range=-s34228 --lua-desync=circular --lua-desync=argdebug:strategy=1 --lua-desync=argdebug:strategy=2
|
||||
function circular(ctx, desync)
|
||||
local function count_strategies(hrec)
|
||||
if not hrec.ctstrategy then
|
||||
@@ -223,26 +363,11 @@ function circular(ctx, desync)
|
||||
local verdict = VERDICT_PASS
|
||||
if hrec.final~=hrec.nstrategy then
|
||||
local crec = automate_conn_record(desync)
|
||||
local fails = tonumber(desync.arg.fails) or 3
|
||||
local maxtime = tonumber(desync.arg.time) or 60
|
||||
local failure_detector
|
||||
if desync.arg.detector then
|
||||
if type(_G[desync.arg.detector])~="function" then
|
||||
error("circular: invalid failure detector function '"..desync.arg.detector.."'")
|
||||
end
|
||||
failure_detector = _G[desync.arg.detector]
|
||||
else
|
||||
failure_detector = standard_failure_detector
|
||||
end
|
||||
if failure_detector(desync,crec,desync.arg) then
|
||||
-- failure happened. count failures.
|
||||
if automate_failure_counter(hrec, crec, fails, maxtime) then
|
||||
-- counter reaches threshold. circular strategy change
|
||||
hrec.nstrategy = (hrec.nstrategy % hrec.ctstrategy) + 1
|
||||
DLOG("circular: rotate strategy to "..hrec.nstrategy)
|
||||
if hrec.nstrategy == hrec.final then
|
||||
DLOG("circular: final strategy "..hrec.final.." reached. will rotate no more.")
|
||||
end
|
||||
if automate_failure_check(desync, hrec, crec) then
|
||||
hrec.nstrategy = (hrec.nstrategy % hrec.ctstrategy) + 1
|
||||
DLOG("circular: rotate strategy to "..hrec.nstrategy)
|
||||
if hrec.nstrategy == hrec.final then
|
||||
DLOG("circular: final strategy "..hrec.final.." reached. will rotate no more.")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -271,15 +396,43 @@ 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)
|
||||
if not desync.arg.pattern then
|
||||
error("cond_payload_str: missing 'pattern'")
|
||||
end
|
||||
return string.find(desync.dis.payload,desync.arg.pattern,1,true)
|
||||
return desync.dis.payload and string.find(desync.dis.payload,desync.arg.pattern,1,true)
|
||||
end
|
||||
-- true if dissect is tcp and timestamp tcp option is present
|
||||
function cond_tcp_has_ts(desync)
|
||||
return desync.dis.tcp and find_tcp_option(desync.dis.tcp.options, TCP_KIND_TS)
|
||||
end
|
||||
-- exec lua code in "code" arg and return it's result
|
||||
function cond_lua(desync)
|
||||
if not desync.arg.cond_code then
|
||||
error("cond_lua: no 'cond_code' parameter")
|
||||
end
|
||||
local fname = desync.func_instance.."_cond_cond_code"
|
||||
if not _G[fname] then
|
||||
local err
|
||||
_G[fname], err = load(desync.arg.cond_code, fname)
|
||||
if not _G[fname] then
|
||||
error(err)
|
||||
return
|
||||
end
|
||||
end
|
||||
-- allow dynamic cond_code to access desync
|
||||
_G.desync = desync
|
||||
local res, v = pcall(_G[fname])
|
||||
_G.desync = nil
|
||||
if not res then
|
||||
error(v);
|
||||
end
|
||||
return v
|
||||
end
|
||||
|
||||
-- check iff function available. error if not
|
||||
function require_iff(desync, name)
|
||||
if not desync.arg.iff then
|
||||
@@ -293,23 +446,62 @@ 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
|
||||
-- arg: instances - how many instances execute conditionally. all if not defined
|
||||
-- test case : --lua-desync=condition:iff=cond_random --lua-desync=argdebug:testarg=1 --lua-desync=argdebug:testarg=2:morearg=xyz
|
||||
function condition(ctx, desync)
|
||||
require_iff(desync, "condition")
|
||||
orchestrate(ctx, desync)
|
||||
if logical_xor(_G[desync.arg.iff](desync), desync.arg.neg) then
|
||||
DLOG("condition: true")
|
||||
return replay_execution_plan(desync)
|
||||
else
|
||||
DLOG("condition: false")
|
||||
plan_clear(desync)
|
||||
plan_clear(desync, tonumber(desync.arg.instances))
|
||||
if #desync.plan>0 then
|
||||
DLOG("condition: executing remaining "..#desync.plan.." instance(s)")
|
||||
end
|
||||
end
|
||||
return replay_execution_plan(desync)
|
||||
end
|
||||
-- execute further desync instances.
|
||||
-- each instance may have "cond" and "cond_neg" args.
|
||||
-- "cond" - condition function. "neg" - invert condition function result
|
||||
-- arg: instances - how many instances execute conditionally. all if not defined
|
||||
function per_instance_condition(ctx, desync)
|
||||
orchestrate(ctx, desync)
|
||||
|
||||
local verdict = VERDICT_PASS
|
||||
local n = 0
|
||||
local max = tonumber(desync.arg.instances)
|
||||
while not max or n<max do
|
||||
local instance = plan_instance_pop(desync)
|
||||
if not instance then break end
|
||||
if instance.arg.cond then
|
||||
if type(_G[instance.arg.cond])~="function" then
|
||||
error("per_instance_condition: invalid 'iff' function '"..instance.arg.cond.."'")
|
||||
end
|
||||
-- preapply exec plan to feed cond function correct args
|
||||
apply_execution_plan(desync, instance)
|
||||
if logical_xor(_G[instance.arg.cond](desync), instance.arg.cond_neg) then
|
||||
verdict = plan_instance_execute_preapplied(desync, verdict, instance)
|
||||
else
|
||||
DLOG("per_instance_condition: condition not satisfied. skipping '"..instance.func_instance.."'")
|
||||
end
|
||||
else
|
||||
DLOG("per_instance_condition: no 'cond' arg in '"..instance.func_instance.."'. skipping")
|
||||
end
|
||||
n = n + 1
|
||||
end
|
||||
if #desync.plan>0 then
|
||||
DLOG("per_instance_condition: executing remaining "..#desync.plan.." instance(s) unconditionally")
|
||||
end
|
||||
return verdict_aggregate(verdict, replay_execution_plan(desync))
|
||||
end
|
||||
|
||||
-- clear execution plan if user provided 'iff' functions returns true
|
||||
-- can be used with other orchestrators to stop execution conditionally
|
||||
-- arg: iff - condition function. takes desync as arg and returns bool. (cant use 'if' because of reserved word)
|
||||
-- arg: neg - invert condition function result
|
||||
-- test case : nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-auto.lua --in-range=-s1 --lua-desync=circular --lua-desync=stopif:iff=cond_random:strategy=1 --lua-desync=argdebug:strategy=1 --lua-desync=argdebug:strategy=2
|
||||
-- test case : --in-range=-s1 --lua-desync=circular --lua-desync=stopif:iff=cond_random:strategy=1 --lua-desync=argdebug:strategy=1 --lua-desync=argdebug:strategy=2
|
||||
function stopif(ctx, desync)
|
||||
require_iff(desync, "stopif")
|
||||
orchestrate(ctx, desync)
|
||||
@@ -321,3 +513,65 @@ 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("repeater: missing 'repeats'")
|
||||
end
|
||||
local iff = desync.arg.iff or "cond_true"
|
||||
if type(_G[iff])~="function" then
|
||||
error("repeater: invalid 'iff' function '"..iff.."'")
|
||||
end
|
||||
orchestrate(ctx, desync)
|
||||
if #desync.plan==0 then
|
||||
DLOG("repeater: execution plan is empty - nothing to repeat")
|
||||
return
|
||||
end
|
||||
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
|
||||
|
||||
1616
lua/zapret-lib.lua
1616
lua/zapret-lib.lua
File diff suppressed because it is too large
Load Diff
482
lua/zapret-obfs.lua
Normal file
482
lua/zapret-obfs.lua
Normal file
@@ -0,0 +1,482 @@
|
||||
-- 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
|
||||
-- reduce MTU of wireguard interface to avoid ip fragmentation !
|
||||
-- without knowing the secret encrypted packets should be crypto strong white noise with no signature
|
||||
-- arg : secret - shared secret. any string. must be the same on both peers
|
||||
-- arg : padmin - min random garbage bytes. 0 by default
|
||||
-- arg : padmax - max random garbage bytes. 16 by default
|
||||
-- NOTE : this function does not depend on zapret-lib.lua and should not be run under orchestrator (uses direct instance_cutoff)
|
||||
function wgobfs(ctx, desync)
|
||||
if not desync.dis.udp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
|
||||
local padmin = desync.arg.padmin and tonumber(desync.arg.padmin) or 0
|
||||
local padmax = desync.arg.padmax and tonumber(desync.arg.padmax) or 16
|
||||
local function genkey()
|
||||
-- cache key in a global var bound to instance name
|
||||
local key_cache_name = desync.func_instance.."_key"
|
||||
local key = _G[key_cache_name]
|
||||
if not key then
|
||||
key = hkdf("sha256", "wgobfs_salt", desync.arg.secret, nil, 16)
|
||||
_G[key_cache_name] = key
|
||||
end
|
||||
return key
|
||||
end
|
||||
local function maybe_encrypted_payload(payload)
|
||||
for k,plsize in pairs({2+12+16+148, 2+12+16+92, 2+12+16+64}) do
|
||||
if #payload>=(plsize+padmin) and #payload<=(plsize+padmax) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
local function wg_payload_from_size(payload)
|
||||
if #payload==148 then return "wireguard_initiation"
|
||||
elseif #payload==92 then return "wireguard_response"
|
||||
elseif #payload==64 then return "wireguard_cookie"
|
||||
else return nil
|
||||
end
|
||||
end
|
||||
|
||||
if not desync.arg.secret or #desync.arg.secret==0 then
|
||||
error("wgobfs: secret required")
|
||||
end
|
||||
if padmin>padmax then
|
||||
error("wgobfs: padmin>padmax")
|
||||
end
|
||||
if (desync.l7payload=="wireguard_initiation" or desync.l7payload=="wireguard_response" or desync.l7payload=="wireguard_cookie") and #desync.dis.payload<65506 then
|
||||
DLOG("wgobfs: encrypting '"..desync.l7payload.."'. size "..#desync.dis.payload)
|
||||
local key = genkey()
|
||||
-- in aes-gcm every message require it's own crypto secure random iv
|
||||
-- encrypting more than one message with the same iv is considered catastrophic failure
|
||||
-- iv must be sent with encrypted message
|
||||
local iv = bcryptorandom(12)
|
||||
local encrypted, atag = aes_gcm(true, key, iv, bu16(#desync.dis.payload)..desync.dis.payload..brandom(math.random(padmin,padmax)), nil)
|
||||
desync.dis.payload = iv..atag..encrypted
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
|
||||
if desync.l7payload=="unknown" and maybe_encrypted_payload(desync.dis.payload) then
|
||||
local key = genkey()
|
||||
local iv = string.sub(desync.dis.payload,1,12)
|
||||
local atag = string.sub(desync.dis.payload,13,28)
|
||||
local decrypted, atag2 = aes_gcm(false, key, iv, string.sub(desync.dis.payload,29))
|
||||
if atag==atag2 then
|
||||
local plen = u16(decrypted)
|
||||
if plen>(#decrypted-2) then
|
||||
DLOG("wgobfs: bad decrypted payload data")
|
||||
else
|
||||
desync.dis.payload = string.sub(decrypted, 3, 3+plen-1)
|
||||
if b_debug then DLOG("wgobfs: decrypted '"..(wg_payload_from_size(desync.dis.payload) or "unknown").."' message. size "..plen) end
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
else
|
||||
DLOG("wgobfs: decrypt auth tag mismatch")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- test case :
|
||||
-- endpoint1:
|
||||
-- --filter-icmp=0,8,128,129 --filter-ipp=193,198,209,250 --filter-tcp=* --filter-udp=* --in-range=a --lua-desync=ippxor:ippxor=192:dataxor=0xABCD
|
||||
-- nft add rule inet ztest pre meta mark and 0x40000000 == 0 meta l4proto {193, 198, 209, 250} queue num 200 bypass
|
||||
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 tcp dport "{5001}" queue num 200 bypass
|
||||
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 udp dport "{5001}" queue num 200 bypass
|
||||
-- iperf -i 1 -c endpoint2
|
||||
-- endpoint2:
|
||||
-- --filter-icmp=0,8,128,129 --filter-ipp=193,198,209,250 --filter-tcp=* --filter-udp=* --in-range=a --lua-desync=ippxor:ippxor=192:dataxor=0xABCD --server
|
||||
-- nft add rule inet ztest pre meta mark and 0x40000000 == 0 meta l4proto {193, 198, 209, 250} queue num 200 bypass
|
||||
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 tcp sport "{5001}" queue num 200 bypass
|
||||
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 udp sport "{5001}" queue num 200 bypass
|
||||
-- iperf -s
|
||||
-- xor ip protocol number and optionally xor tcp,udp,icmp payload with supplied blob pattern
|
||||
-- arg : ippxor - value to xor ip protocol number
|
||||
-- arg : dataxor - blob to xor tcp, udp or icmp payload
|
||||
-- arg : rebuild - always reconstruct desync.dis if after ippxor packet becomes tcp,udp or icmp
|
||||
function ippxor(ctx, desync)
|
||||
local dataxor
|
||||
local function need_dxor(dis)
|
||||
return dataxor and dis.payload and #dis.payload>0 and (dis.tcp or dis.udp or dis.icmp)
|
||||
end
|
||||
local function dxor(dis)
|
||||
dis.payload = bxor(dis.payload, pattern(dataxor,1,#dis.payload))
|
||||
end
|
||||
|
||||
if not desync.arg.ippxor then
|
||||
error("ippxor: ippxor value required")
|
||||
end
|
||||
local ippxor = tonumber(desync.arg.ippxor)
|
||||
if ippxor<0 or ippxor>0xFF then
|
||||
error("ippxor: invalid ippxor value. should be 0..255")
|
||||
end
|
||||
if desync.arg.dataxor then
|
||||
dataxor = blob(desync,desync.arg.dataxor)
|
||||
if #dataxor==0 then
|
||||
error("ippxor: empty dataxor value")
|
||||
end
|
||||
end
|
||||
|
||||
local bdxor = need_dxor(desync.dis)
|
||||
if bdxor then
|
||||
DLOG("ippxor: dataxor size="..#desync.dis.payload)
|
||||
dxor(desync.dis)
|
||||
end
|
||||
|
||||
local l3_from = ip_proto_l3(desync.dis)
|
||||
local l3_to = bitxor(l3_from, ippxor)
|
||||
DLOG("ippxor: "..l3_from.." => "..l3_to)
|
||||
fix_ip_proto(desync.dis, l3_to)
|
||||
|
||||
if (not bdxor and dataxor or desync.arg.rebuild) and
|
||||
(l3_to==IPPROTO_TCP and not desync.dis.tcp or
|
||||
l3_to==IPPROTO_UDP and not desync.dis.udp or
|
||||
l3_to==IPPROTO_ICMP and not (desync.dis.ip and desync.dis.icmp) or
|
||||
l3_to==IPPROTO_ICMPV6 and not (desync.dis.ip6 and desync.dis.icmp))
|
||||
then
|
||||
DLOG("ippxor: packet rebuild")
|
||||
local raw_ip = reconstruct_dissect(desync.dis, {ip6_preserve_next=true})
|
||||
local dis = dissect(raw_ip)
|
||||
if not dis.ip and not dis.ip6 then
|
||||
DLOG_ERR("ippxor: could not rebuild packet")
|
||||
return
|
||||
end
|
||||
desync.dis = dis
|
||||
end
|
||||
|
||||
if not bdxor and need_dxor(desync.dis) then
|
||||
DLOG("ippxor: dataxor size="..#desync.dis.payload)
|
||||
dxor(desync.dis)
|
||||
end
|
||||
|
||||
return VERDICT_MODIFY + VERDICT_PRESERVE_NEXT
|
||||
end
|
||||
|
||||
-- test case:
|
||||
-- endpoint1:
|
||||
-- --in-range=a --lua-desync=udp2icmp
|
||||
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 udp dport 12345 queue num 200 bypass
|
||||
-- nft add rule inet ztest pre meta mark and 0x40000000 == 0 meta l4proto "{icmp,icmpv6}" queue num 200 bypass
|
||||
-- endpoint2:
|
||||
-- --in-range=a --lua-desync=udp2icmp --server
|
||||
-- nft add rule inet ztest post meta mark and 0x40000000 == 0 udp sport 12345 queue num 200 bypass
|
||||
-- nft add rule inet ztest pre meta mark and 0x40000000 == 0 meta l4proto "{icmp,icmpv6}" queue num 200 bypass
|
||||
-- packs udp datagram to icmp message without changing packet size
|
||||
-- function keeps icmp identifier as (sport xor dport) to help traverse NAT (it won't help if NAT changes id)
|
||||
-- one end must be in server mode, another - in client mode
|
||||
-- arg : ctype - client icmp type
|
||||
-- arg : ccode - client icmp code
|
||||
-- arg : stype - server icmp type
|
||||
-- arg : scode - server icmp code
|
||||
-- arg : dataxor - blob to xor udp payload
|
||||
-- arg : server=[0|1] - override server mode. by default use "--server" nfqws2 parameter
|
||||
function udp2icmp(ctx, desync)
|
||||
local dataxor
|
||||
local bserver = desync.arg.server and (desync.arg.server~="0") or b_server
|
||||
|
||||
local function one_byte_arg(name)
|
||||
if desync.arg[name] then
|
||||
local v = tonumber(desync.arg[name])
|
||||
if v<0 or v>0xFF then
|
||||
error("udp2icmp: invalid type or code value. should be 0..255")
|
||||
end
|
||||
return v
|
||||
end
|
||||
end
|
||||
local function ictype(send)
|
||||
local ctype = one_byte_arg("ctype")
|
||||
local stype = one_byte_arg("stype")
|
||||
if logical_xor(ctype,stype) then
|
||||
error("udp2icmp: ctype and stype must be both set or not set")
|
||||
end
|
||||
if not ctype then
|
||||
ctype = desync.dis.ip6 and ICMP6_ECHO_REQUEST or ICMP_ECHO
|
||||
stype = desync.dis.ip6 and ICMP6_ECHO_REPLY or ICMP_ECHOREPLY
|
||||
end
|
||||
return logical_xor(send,bserver) and ctype or stype
|
||||
end
|
||||
local function iccode(send)
|
||||
local ccode = one_byte_arg("ccode")
|
||||
local scode = one_byte_arg("scode")
|
||||
if logical_xor(ccode,scode) then
|
||||
error("udp2icmp: ccode and scode must be both set or not set")
|
||||
end
|
||||
if not ccode then
|
||||
ccode = 0
|
||||
scode = 0
|
||||
end
|
||||
return logical_xor(send,bserver) and ccode or scode
|
||||
end
|
||||
local function plxor()
|
||||
if dataxor then
|
||||
DLOG("udp2icmp: dataxor")
|
||||
desync.dis.payload = bxor(desync.dis.payload, pattern(dataxor,1,#desync.dis.payload))
|
||||
end
|
||||
end
|
||||
|
||||
if desync.arg.dataxor then
|
||||
dataxor = blob(desync,desync.arg.dataxor)
|
||||
if #dataxor==0 then
|
||||
error("udp2icmp: empty dataxor value")
|
||||
end
|
||||
end
|
||||
|
||||
if desync.dis.udp then
|
||||
plxor()
|
||||
if b_debug then -- save some cpu
|
||||
DLOG("udp2icmp: udp => icmp sport="..desync.dis.udp.uh_sport.." dport="..desync.dis.udp.uh_dport.." size="..#desync.dis.payload)
|
||||
end
|
||||
desync.dis.icmp = {
|
||||
icmp_type = ictype(true),
|
||||
icmp_code = iccode(true),
|
||||
icmp_data = u32(
|
||||
bu16(bitxor(desync.dis.udp.uh_sport,desync.dis.udp.uh_dport))..
|
||||
(bserver and bu16(desync.dis.udp.uh_sport) or bu16(desync.dis.udp.uh_dport)))
|
||||
}
|
||||
desync.dis.udp = nil
|
||||
fix_ip_proto(desync.dis)
|
||||
return VERDICT_MODIFY
|
||||
elseif desync.dis.icmp and desync.dis.icmp.icmp_type==ictype(false) and desync.dis.icmp.icmp_code==iccode(false) then
|
||||
local pl = bitand(desync.dis.icmp.icmp_data,0xFFFF)
|
||||
local pm = bitxor(bitrshift(desync.dis.icmp.icmp_data,16),pl)
|
||||
desync.dis.udp = {
|
||||
uh_sport = bserver and pm or pl,
|
||||
uh_dport = bserver and pl or pm,
|
||||
uh_ulen = UDP_BASE_LEN + #desync.dis.payload
|
||||
}
|
||||
desync.dis.icmp = nil
|
||||
fix_ip_proto(desync.dis)
|
||||
if b_debug then -- save some cpu
|
||||
DLOG("udp2icmp: icmp => udp sport="..desync.dis.udp.uh_sport.." dport="..desync.dis.udp.uh_dport.." size="..#desync.dis.payload)
|
||||
end
|
||||
plxor()
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
test case :
|
||||
both:
|
||||
nft create table inet ztest
|
||||
nft add chain inet ztest post "{type filter hook output priority mangle;}"
|
||||
nft add chain inet ztest pre "{type filter hook input priority mangle;}"
|
||||
nft add chain inet ztest predefrag "{type filter hook output priority -401;}"
|
||||
nft add rule inet ztest predefrag "mark & 0x40000000 != 0x00000000 notrack"
|
||||
client:
|
||||
--in-range="<d1" --out-range="<d1" --lua-desync=synhide:synack:ghost=2
|
||||
nft add rule inet ztest post "meta mark & 0x40000000 == 0x00000000 tcp dport { 80, 443 } tcp flags & (fin | syn | rst | ack | urg) == syn queue flags bypass to 200"
|
||||
nft add rule inet ztest pre meta "mark & 0x40000000 == 0x00000000 tcp sport { 80, 443 } tcp flags & (fin | syn | rst | ack | urg) == (rst | ack) tcp urgptr != 0 queue flags bypass to 200"
|
||||
nft add rule inet ztest pre meta "mark & 0x40000000 == 0x00000000 tcp sport { 80, 443 } tcp flags & (fin | syn | rst | ack | urg) == (rst | ack) tcp option 172 exists queue flags bypass to 200"
|
||||
nft add rule inet ztest pre meta "mark & 0x40000000 == 0x00000000 tcp sport { 80, 443 } tcp flags & (fin | syn | rst | ack | urg) == (rst | ack) @th,100,4 != 0 queue flags bypass to 200"
|
||||
server:
|
||||
--in-range=a --lua-desync=synhide:synack
|
||||
nft add rule inet ztest post "meta mark & 0x40000000 == 0x00000000 tcp sport { 80, 443 } tcp flags & (fin | syn | rst | ack | urg) == (syn | ack) queue flags bypass to 200"
|
||||
nft add rule inet ztest pre "meta mark & 0x40000000 == 0x00000000 tcp dport { 80, 443 } tcp flags & (fin | syn | rst | ack | urg) == ack tcp urgptr != 0 queue flags bypass to 200"
|
||||
nft add rule inet ztest pre "meta mark & 0x40000000 == 0x00000000 tcp dport { 80, 443 } tcp flags & (fin | syn | rst | ack | urg) == ack tcp option 172 exists queue flags bypass to 200"
|
||||
nft add rule inet ztest pre "meta mark & 0x40000000 == 0x00000000 tcp dport { 80, 443 } tcp flags & (fin | syn | rst | ack | urg) == ack @th,100,4 != 0 queue flags bypass to 200"
|
||||
nft add rule inet ztest pre "meta mark & 0x40000000 == 0x00000000 tcp dport { 80, 443 } tcp flags & (fin | syn | rst | ack | urg) == ack ct state new queue flags bypass to 200"
|
||||
|
||||
hides tcp handshake from DPI optionally using ghost SYN packet with low ttl to punch NAT hole
|
||||
NOTE: linux conntrack treats packets without SYN in SYN_SENT state as INVALID ! NAT does not work !
|
||||
NOTE: the only found workaround - put NFQUEUE handler to that packet. It should only return pass verdict.
|
||||
NOTE: BSD and CGNAT should work
|
||||
NOTE: won't likely pass home routers even with hardware offload enabled - SYN state is managed in netfilter before offload. but can work from router itself.
|
||||
|
||||
arg : ghost - ghost syn ttl for ipv4. must be hop_to_last_nat+1. syn is not ghosted if not supplied
|
||||
arg : ghost6 - ghost syn hl for ipv6. must be hop_to_last_nat+1. syn is not ghosted if not supplied
|
||||
arg : synack - also fake synack. NOTE: will likely not work with magic=tsecr on *nix clients because they expect valid echoed tsecr in SYN,ACK
|
||||
arg : magic=[x2|urp|opt|tsecr] - where to put magic value to recognize modified packets
|
||||
arg : x2=bit - th_x2 bit used for magic=x2 - 1,2,4,8
|
||||
arg : kind - kind of tcp option for magic=opt
|
||||
arg : opt=hex - tcp option value
|
||||
arg : xorseq=hex - 4 hex bytes to xor seq
|
||||
--]]
|
||||
function synhide(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
|
||||
local fl = bitand(desync.dis.tcp.th_flags, TH_SYN+TH_ACK+TH_FIN+TH_RST+TH_URG)
|
||||
local tsidx = find_tcp_option(desync.dis.tcp.options, TCP_KIND_TS)
|
||||
local magic
|
||||
if desync.arg.magic then
|
||||
if desync.arg.magic~="tsecr" and desync.arg.magic~="x2" and desync.arg.magic~="urp" and desync.arg.magic~="opt" then
|
||||
error("synhide: invalid magic mode '"..desync.arg.magic.."'")
|
||||
end
|
||||
magic = desync.arg.magic
|
||||
if magic=="tsecr" and not tsidx then
|
||||
DLOG("synhide: cannot use tsecr magic because timestamp option is absent")
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
else
|
||||
magic = "x2"
|
||||
end
|
||||
DLOG("synhide: magic="..magic)
|
||||
|
||||
local x2
|
||||
if desync.arg.x2 then
|
||||
x2 = tonumber(desync.arg.x2)
|
||||
if x2<1 or x2>0x0F then
|
||||
error("synhide: invalid x2 value")
|
||||
end
|
||||
else
|
||||
-- some firewalls allow only AECN bit (1). if reserved bits are !=0 => administratively prohibited
|
||||
x2 = 1
|
||||
end
|
||||
|
||||
local kind
|
||||
if desync.arg.kind then
|
||||
kind = tonumber(desync.arg.kind)
|
||||
-- do not allow noop and end
|
||||
if kind<2 or kind>0xFF then
|
||||
error("synhide: invalid kind value")
|
||||
end
|
||||
else
|
||||
kind = 172 -- accurate ecn
|
||||
end
|
||||
|
||||
local opt
|
||||
if desync.arg.opt then
|
||||
opt = parse_hex(desync.arg.opt)
|
||||
if not opt then
|
||||
error("synhide: invalid opt value")
|
||||
end
|
||||
else
|
||||
opt=""
|
||||
end
|
||||
|
||||
|
||||
local xorseq
|
||||
if desync.arg.xorseq then
|
||||
xorseq = parse_hex(desync.arg.xorseq)
|
||||
if not xorseq or #xorseq~=4 then
|
||||
error("synhide: invalid xorseq value")
|
||||
end
|
||||
xorseq = u32(xorseq)
|
||||
end
|
||||
|
||||
local function make_magic(client)
|
||||
local m
|
||||
-- use client seq0
|
||||
m = client and desync.dis.tcp.th_seq or desync.dis.tcp.th_ack-1
|
||||
m = bitxor(bitrshift(m,16),bitand(m,0xFFFF))
|
||||
if m==0 then
|
||||
-- 0 is not acceptable
|
||||
m = client and desync.dis.tcp.th_dport or desync.dis.tcp.th_sport
|
||||
end
|
||||
return m
|
||||
end
|
||||
local function xorhdr()
|
||||
if xorseq then
|
||||
desync.dis.tcp.th_ack = bitxor(desync.dis.tcp.th_ack, xorseq)
|
||||
desync.dis.tcp.th_seq = bitxor(desync.dis.tcp.th_seq, xorseq)
|
||||
end
|
||||
end
|
||||
local function ver_magic(client)
|
||||
local r = false
|
||||
xorhdr()
|
||||
if magic=="tsecr" then
|
||||
r = make_magic(client)==u16(string.sub(desync.dis.tcp.options[tsidx].data,7))
|
||||
elseif magic=="x2" then
|
||||
r = bitand(desync.dis.tcp.th_x2, x2)~=0
|
||||
elseif magic=="urp" then
|
||||
r = desync.dis.tcp.th_urp == make_magic(client)
|
||||
elseif magic=="opt" then
|
||||
local idx = find_tcp_option(desync.dis.tcp.options, kind)
|
||||
r = idx and desync.dis.tcp.options[idx].data == opt
|
||||
end
|
||||
xorhdr()
|
||||
return r
|
||||
end
|
||||
local function set_magic(client)
|
||||
if magic=="tsecr" then
|
||||
desync.dis.tcp.options[tsidx].data = string.sub(desync.dis.tcp.options[tsidx].data,1,6) .. bu16(make_magic(client))
|
||||
elseif magic=="x2" then
|
||||
desync.dis.tcp.th_x2 = bitor(desync.dis.tcp.th_x2, x2)
|
||||
elseif magic=="urp" then
|
||||
desync.dis.tcp.th_urp = make_magic(client)
|
||||
elseif magic=="opt" then
|
||||
table.insert(desync.dis.tcp.options, {kind=kind, data=opt})
|
||||
end
|
||||
xorhdr()
|
||||
end
|
||||
local function clear_magic()
|
||||
xorhdr()
|
||||
if magic=="tsecr" then
|
||||
desync.dis.tcp.options[tsidx].data = string.sub(desync.dis.tcp.options[tsidx].data,1,6) .. "\x00\x00"
|
||||
elseif magic=="x2" then
|
||||
desync.dis.tcp.th_x2 = bitand(desync.dis.tcp.th_x2,bitnot(x2))
|
||||
elseif magic=="urp" then
|
||||
desync.dis.tcp.th_urp = 0
|
||||
elseif magic=="opt" then
|
||||
local idx = find_tcp_option(desync.dis.tcp.options, kind)
|
||||
if idx then
|
||||
table.remove(desync.dis.tcp.options, idx)
|
||||
end
|
||||
end
|
||||
desync.track = conntrack_feed(desync.dis)
|
||||
end
|
||||
|
||||
if fl==TH_SYN then
|
||||
-- client sent
|
||||
local ttl = tonumber(desync.dis.ip and desync.arg.ghost or desync.arg.ghost6)
|
||||
if ttl then
|
||||
DLOG("synhide: punch NAT hole with ttl="..ttl)
|
||||
local dis = deepcopy(desync.dis)
|
||||
if dis.ip then
|
||||
dis.ip.ip_ttl = ttl
|
||||
elseif dis.ip6 then
|
||||
dis.ip6.ip6_hlim = ttl
|
||||
end
|
||||
if not rawsend_dissect(dis, rawsend_opts_base(desync)) then
|
||||
instance_cutoff_shim(ctx, desync) -- failed
|
||||
return
|
||||
end
|
||||
end
|
||||
DLOG("synhide: client sends SYN. remove SYN")
|
||||
set_magic(true)
|
||||
-- remove SYN, set ACK
|
||||
desync.dis.tcp.th_flags = bitor(bitand(desync.dis.tcp.th_flags, bitnot(TH_SYN)), TH_ACK)
|
||||
if not desync.arg.synack then
|
||||
DLOG("synhide: mission complete")
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
return VERDICT_MODIFY
|
||||
elseif fl==(TH_SYN+TH_ACK) then
|
||||
-- server sent
|
||||
if desync.arg.synack then
|
||||
DLOG("synhide: server sends SYN+ACK. remove SYN, set RST")
|
||||
set_magic(false)
|
||||
desync.dis.tcp.th_flags = bitor(bitand(desync.dis.tcp.th_flags, bitnot(TH_SYN)), TH_RST)
|
||||
return VERDICT_MODIFY
|
||||
else
|
||||
DLOG("synhide: server sends SYN+ACK. do not remove SYN because 'synack' arg is not set.")
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return -- do nothing
|
||||
end
|
||||
elseif fl==TH_ACK and ver_magic(true) then
|
||||
DLOG("synhide: server received magic. restore SYN")
|
||||
desync.dis.tcp.th_flags = bitor(bitand(desync.dis.tcp.th_flags, bitnot(TH_ACK)), TH_SYN)
|
||||
clear_magic()
|
||||
if not desync.arg.synack then
|
||||
DLOG("synhide: mission complete")
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
return VERDICT_MODIFY
|
||||
elseif fl==(TH_ACK+TH_RST) and ver_magic(false) then
|
||||
DLOG("synhide: client received magic. restore SYN, remove RST")
|
||||
desync.dis.tcp.th_flags = bitor(bitand(desync.dis.tcp.th_flags, bitnot(TH_RST)), TH_SYN)
|
||||
clear_magic()
|
||||
DLOG("synhide: mission complete")
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
|
||||
DLOG("synhide: sequence failed")
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
@@ -1,12 +1,11 @@
|
||||
function pcap_write_header(file)
|
||||
-- big endian, nanoseconds in timestamps, ver 2.4, max packet size - 0x4000 (16384), 0x65 - l3 packets without l2
|
||||
file:write("\xA1\xB2\x3C\x4D\x00\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x65")
|
||||
-- big endian, nanoseconds in timestamps, ver 2.4, max packet size - 0xFFFF (65535), 0x65 - l3 packets without l2
|
||||
file:write("\xA1\xB2\x3C\x4D\x00\x02\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00\x00\x65")
|
||||
end
|
||||
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)
|
||||
@@ -31,9 +30,11 @@ function pcap(ctx, desync)
|
||||
os.remove(_G[fn_cache_name])
|
||||
end
|
||||
end
|
||||
local f = io.open(_G[fn_cache_name], "a")
|
||||
local f = io.open(_G[fn_cache_name], "ab")
|
||||
if not f then
|
||||
error("pcap: could not write to '".._G[fn_cache_name].."'")
|
||||
end
|
||||
pcap_write(f, raw_packet(ctx))
|
||||
local raw = ctx and raw_packet(ctx) or reconstruct_dissect(desync.dis)
|
||||
pcap_write(f, raw)
|
||||
f:close()
|
||||
end
|
||||
|
||||
@@ -13,15 +13,19 @@ end
|
||||
|
||||
|
||||
function test_all(...)
|
||||
test_run({test_crypto, test_bin, test_ipstr, test_dissect, test_csum, test_resolve, test_rawsend},...)
|
||||
test_run({
|
||||
test_crypto, test_bin, test_time, test_gzip, test_ipstr, test_dissect, test_csum, test_resolve,
|
||||
test_get_source_ip, test_ifaddrs, test_rawsend},...)
|
||||
end
|
||||
|
||||
|
||||
function test_crypto(...)
|
||||
test_run({test_random, test_aes, test_aes_gcm, test_aes_ctr, test_hkdf, test_hash},...)
|
||||
test_run({test_random, test_bop, test_aes, test_aes_gcm, test_aes_ctr, test_hkdf, test_hash},...)
|
||||
end
|
||||
|
||||
function test_random()
|
||||
print("* random")
|
||||
|
||||
local rnds={}
|
||||
for i=1,20 do
|
||||
local rnd = bcryptorandom(math.random(10,20))
|
||||
@@ -31,7 +35,35 @@ function test_random()
|
||||
end
|
||||
end
|
||||
|
||||
function test_bop()
|
||||
print("* bop")
|
||||
|
||||
for n,test in ipairs(
|
||||
{
|
||||
{ fb = bxor, fbit = bitxor, nb = "bxor", nbit="bitxor" },
|
||||
{ fb = bor, fbit = bitor, nb = "bor", nbit="bitor" },
|
||||
{ fb = band, fbit = bitand, nb = "band", nbit="bitand" }
|
||||
}) do
|
||||
for k=1,5 do
|
||||
local r = {}
|
||||
for i=1,6 do r[i] = math.random(0,0xFFFFFFFFFFFF) end
|
||||
local v1 = bu48(r[1])..bu48(r[2])..bu48(r[3])
|
||||
local v2 = bu48(r[4])..bu48(r[5])..bu48(r[6])
|
||||
print("x1 : "..string2hex(v1))
|
||||
print("x2 : "..string2hex(v2))
|
||||
local v3 = test.fb(v1,v2)
|
||||
local v4 = bu48(test.fbit(r[1],r[4]))..bu48(test.fbit(r[2],r[5]))..bu48(test.fbit(r[3],r[6]))
|
||||
print(test.nb.." : "..string2hex(v3))
|
||||
print(test.nbit.." : "..string2hex(v4))
|
||||
print("result : "..(v3==v4 and "OK" or "FAIL"))
|
||||
test_assert(v3==v4)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function test_hash()
|
||||
print("* hash")
|
||||
|
||||
local hashes={}
|
||||
for i=1,5 do
|
||||
local rnd = brandom(math.random(5,64))
|
||||
@@ -48,6 +80,8 @@ function test_hash()
|
||||
end
|
||||
|
||||
function test_hkdf()
|
||||
print("* hkdf")
|
||||
|
||||
local nblob = 2
|
||||
local okms = {}
|
||||
for nsalt=1,nblob do
|
||||
@@ -56,10 +90,9 @@ function test_hkdf()
|
||||
local ikm = brandom(math.random(5,10))
|
||||
for ninfo=1,nblob do
|
||||
local info = brandom(math.random(5,10))
|
||||
local okm_prev
|
||||
for k,sha in pairs({"sha256","sha224"}) do
|
||||
for k,okml in pairs({8, 16, 50}) do
|
||||
local okm_prev
|
||||
for k,okml in pairs({8, 16, 50}) do
|
||||
local okm
|
||||
print("* hkdf "..sha)
|
||||
print("salt: "..string2hex(salt))
|
||||
@@ -73,7 +106,6 @@ function test_hkdf()
|
||||
print("duplicate okm !")
|
||||
end
|
||||
okms[okm] = true
|
||||
|
||||
test_assert(not okm_prev or okm_prev==string.sub(okm, 1, #okm_prev))
|
||||
okm_prev = okm
|
||||
end
|
||||
@@ -84,6 +116,8 @@ function test_hkdf()
|
||||
end
|
||||
|
||||
function test_aes()
|
||||
print("* aes")
|
||||
|
||||
local clear_text="test "..brandom_az09(11)
|
||||
local iv, key, encrypted, decrypted
|
||||
|
||||
@@ -93,7 +127,7 @@ function test_aes()
|
||||
print()
|
||||
print("* aes test key_size "..tostring(key_size))
|
||||
|
||||
print("clear text: "..clear_text);
|
||||
print("clear text: "..clear_text)
|
||||
|
||||
print("* encrypting")
|
||||
encrypted = aes(true, key, clear_text)
|
||||
@@ -121,6 +155,8 @@ function test_aes()
|
||||
end
|
||||
|
||||
function test_aes_gcm()
|
||||
print("* aes_gcm")
|
||||
|
||||
local authenticated_data = "authenticated message "..brandom_az09(math.random(10,50))
|
||||
local clear_text="test message "..brandom_az09(math.random(10,50))
|
||||
local iv, key, encrypted, atag, decrypted, atag2
|
||||
@@ -132,8 +168,8 @@ function test_aes_gcm()
|
||||
print()
|
||||
print("* aes_gcm test key_size "..tostring(key_size))
|
||||
|
||||
print("clear text: "..clear_text);
|
||||
print("authenticated data: "..authenticated_data);
|
||||
print("clear text: "..clear_text)
|
||||
print("authenticated data: "..authenticated_data)
|
||||
|
||||
print("* encrypting")
|
||||
encrypted, atag = aes_gcm(true, key, iv, clear_text, authenticated_data)
|
||||
@@ -188,6 +224,8 @@ function test_aes_gcm()
|
||||
end
|
||||
|
||||
function test_aes_ctr()
|
||||
print("* aes_ctr")
|
||||
|
||||
local clear_text="test message "..brandom_az09(math.random(10,50))
|
||||
local iv, key, encrypted, decrypted
|
||||
|
||||
@@ -198,7 +236,7 @@ function test_aes_ctr()
|
||||
print()
|
||||
print("* aes_ctr test key_size "..tostring(key_size))
|
||||
|
||||
print("clear text: "..clear_text);
|
||||
print("clear text: "..clear_text)
|
||||
|
||||
print("* encrypting")
|
||||
encrypted = aes_ctr(key, iv, clear_text)
|
||||
@@ -251,61 +289,109 @@ 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
|
||||
print("* ub")
|
||||
|
||||
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
|
||||
|
||||
function test_bit()
|
||||
print("* bit")
|
||||
|
||||
local v, v2, v3, v4, b1, b2, pow
|
||||
|
||||
v = math.random(0,0xFFFFFFFF)
|
||||
b1 = math.random(1,16)
|
||||
for i=1,100 do
|
||||
v = math.random(0,0xFFFFFFFFFFFF)
|
||||
b1 = math.random(1,16)
|
||||
|
||||
v2 = bitrshift(v, b1)
|
||||
pow = 2^b1
|
||||
v3 = divint(v, pow)
|
||||
print(string.format("rshift(0x%X,%u) = 0x%X 0x%X/%u = 0x%X", v,b1,v2, v,pow,v3))
|
||||
v2 = bitrshift(v, b1)
|
||||
pow = 2^b1
|
||||
v3 = divint(v, pow)
|
||||
print(string.format("rshift(0x%X,%u) = 0x%X 0x%X/%u = 0x%X", v,b1,v2, v,pow,v3))
|
||||
test_assert(v2==v3)
|
||||
|
||||
v = math.random(0,0xFFFFFFFFF)
|
||||
b1 = math.random(1,12)
|
||||
v2 = bitlshift(v, b1)
|
||||
pow = 2^b1
|
||||
v3 = (v * pow) % 0x1000000000000
|
||||
print(string.format("lshift(0x%X,%u) = 0x%X 0x%X*%u %% 0x100000000000 = 0x%X", v,b1,v2, v,pow,v3))
|
||||
test_assert(v2==v3)
|
||||
|
||||
v2 = math.random(0,0xFFFFFFFFFFFF)
|
||||
v3 = bitxor(v, v2)
|
||||
v4 = bitor(v, v2) - bitand(v, v2)
|
||||
print(string.format("xor(0x%X,0x%X) = %X or/and/minus = %X", v, v2, v3, v4))
|
||||
test_assert(v3==v4)
|
||||
|
||||
b1 = math.random(1,31)
|
||||
b2 = b1 + math.random(1,16)
|
||||
v2 = bitget(v, b1, b2)
|
||||
pow = 2^(b2-b1+1) - 1
|
||||
v3 = bitand(bitrshift(v,b1), pow)
|
||||
print(string.format("bitget(0x%X,%u,%u) = 0x%X bitand/bitrshift/pow = 0x%X", v, b1, b2, v2, v3))
|
||||
test_assert(v2==v3)
|
||||
|
||||
v4 = math.random(0,pow)
|
||||
v2 = bitset(v, b1, b2, v4)
|
||||
v3 = bitor(bitlshift(v4, b1), bitand(v, bitnot(bitlshift(pow, b1))))
|
||||
print(string.format("bitset(0x%X,%u,%u,0x%X) = 0x%X bitand/bitnot/bitlshift/pow = 0x%X", v, b1, b2, v4, v2, v3))
|
||||
test_assert(v2==v3)
|
||||
end
|
||||
end
|
||||
|
||||
function test_swap()
|
||||
print("* swap")
|
||||
|
||||
local v1, v2, v3
|
||||
|
||||
v1 = math.random(0,0xFFFF)
|
||||
v2 = swap16(v1)
|
||||
v3 = divint(v1,0x100) + v1%0x100*0x100
|
||||
print("swap16: "..(v2==v3 and "OK" or "FAIL"))
|
||||
test_assert(v2==v3)
|
||||
|
||||
v2 = bitlshift(v, b1)
|
||||
pow = 2^b1
|
||||
v3 = (v * pow) % 0x100000000
|
||||
print(string.format("lshift(0x%X,%u) = 0x%X 0x%X*%u %% 0x10000000 = 0x%X", v,b1,v2, v,pow,v3))
|
||||
v1 = math.random(0,0xFFFFFF)
|
||||
v2 = swap24(v1)
|
||||
v3 = divint(v1,0x10000) + divint(v1,0x100)%0x100*0x100 + v1%0x100*0x10000
|
||||
print("swap24: "..(v2==v3 and "OK" or "FAIL"))
|
||||
test_assert(v2==v3)
|
||||
|
||||
v2 = math.random(0,0xFFFFFFFF)
|
||||
v3 = bitxor(v, v2)
|
||||
v4 = bitor(v, v2) - bitand(v, v2)
|
||||
print(string.format("xor(0x%X,0x%X) = %X or/and/minus = %X", v, v2, v3, v4))
|
||||
test_assert(v3==v4)
|
||||
|
||||
b2 = b1 + math.random(1,15)
|
||||
v2 = bitget(v, b1, b2)
|
||||
pow = 2^(b2-b1+1) - 1
|
||||
v3 = bitand(bitrshift(v,b1), pow)
|
||||
print(string.format("bitget(0x%X,%u,%u) = 0x%X bitand/bitrshift/pow = 0x%X", v, b1, b2, v2, v3))
|
||||
v1 = math.random(0,0xFFFFFFFF)
|
||||
v2 = swap32(v1)
|
||||
v3 = divint(v1,0x1000000) + divint(v1,0x10000)%0x100*0x100 + divint(v1,0x100)%0x100*0x10000 + v1%0x100*0x1000000
|
||||
print("swap32: "..(v2==v3 and "OK" or "FAIL"))
|
||||
test_assert(v2==v3)
|
||||
|
||||
v4 = math.random(0,pow)
|
||||
v2 = bitset(v, b1, b2, v4)
|
||||
v3 = bitor(bitlshift(v4, b1), bitand(v, bitnot(bitlshift(pow, b1))))
|
||||
print(string.format("bitset(0x%X,%u,%u,0x%X) = 0x%X bitand/bitnot/bitlshift/pow = 0x%X", v, b1, b2, v4, v2, v3))
|
||||
v1 = math.random(0,0xFFFFFFFFFFFF)
|
||||
v2 = swap48(v1)
|
||||
v3 = divint(v1,0x10000000000) +
|
||||
divint(v1,0x100000000)%0x100*0x100 +
|
||||
divint(v1,0x1000000)%0x100*0x10000 +
|
||||
divint(v1,0x10000)%0x100*0x1000000 +
|
||||
divint(v1,0x100)%0x100*0x100000000 +
|
||||
v1%0x100*0x10000000000
|
||||
print("swap48: "..(v2==v3 and "OK" or "FAIL"))
|
||||
test_assert(v2==v3)
|
||||
end
|
||||
|
||||
function test_ux()
|
||||
print("* ux")
|
||||
|
||||
local v1, v2, v3, usum, sum
|
||||
|
||||
for k,test in pairs({
|
||||
{ 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 +401,7 @@ function test_ux()
|
||||
usum = test.add(v1,v2,v3)
|
||||
sum = bitand((v1+v2+v3)%(test.max+1),test.max)
|
||||
if sum~=usum then
|
||||
print("FAIL")
|
||||
print(string.format("FAIL: 0x%012X + 0x%012X + 0x%012X = 0x%012X 0x%012X",v1,v2,v3,usum,sum))
|
||||
end
|
||||
test_assert(sum==usum)
|
||||
end
|
||||
@@ -324,14 +410,83 @@ function test_ux()
|
||||
end
|
||||
|
||||
function test_bin(...)
|
||||
test_run({test_ub, test_bit, test_ux},...)
|
||||
test_run({test_ub, test_bit, test_swap, test_ux},...)
|
||||
end
|
||||
|
||||
function test_time(...)
|
||||
print("* time")
|
||||
|
||||
local unixtime=os.time()
|
||||
local tm = localtime(unixtime);
|
||||
local t
|
||||
print()
|
||||
print("now: "..tm.str.." "..tm.zone.." = "..unixtime)
|
||||
local tm = gmtime(unixtime);
|
||||
print("gmt: "..tm.str.." "..tm.zone.." = "..unixtime)
|
||||
print()
|
||||
for i=1,20 do
|
||||
unixtime = math.random(0,0x7FFFFFFF);
|
||||
tm = localtime(unixtime);
|
||||
t = timelocal(tm)
|
||||
print("timelocal: "..tm.str.." "..tm.zone.." = "..t)
|
||||
print( t==unixtime and "LOCALTIME OK" or "LOCALTIME FAILED" )
|
||||
test_assert(t==unixtime)
|
||||
|
||||
unixtime = math.random(0,0x7FFFFFFF);
|
||||
tm = gmtime(unixtime);
|
||||
t = timegm(tm)
|
||||
print("timegm: "..tm.str.." "..tm.zone.." = "..t)
|
||||
print( t==unixtime and "GMTIME OK" or "GMTIME FAILED" )
|
||||
test_assert(t==unixtime)
|
||||
end
|
||||
unixtime = math.random(0x80000000,0xFFFFFFFF);
|
||||
tm = gmtime(unixtime)
|
||||
t = timegm(tm)
|
||||
print( t==unixtime and "TIME 0x80000000..0xFFFFFFFF OK" or "TIME 0x80000000..0xFFFFFFFF FAILED : "..unixtime.." != "..t.." ("..tm.str..")" )
|
||||
unixtime = math.random(0x100000000,0x200000000);
|
||||
tm = gmtime(unixtime)
|
||||
t = timegm(tm)
|
||||
print( t==unixtime and "TIME 64 OK" or "TIME 64 FAILED : "..unixtime.." != "..t.." ("..tm.str..")" )
|
||||
end
|
||||
|
||||
function test_gzip()
|
||||
print("* gzip")
|
||||
|
||||
local s=""
|
||||
for i=1,math.random(2000,3000) do
|
||||
local rnd=brandom(math.random(1,50))
|
||||
s=s..rnd..string.rep(bu8(math.random(0,255)),100-#rnd)
|
||||
end
|
||||
local v=math.random(100001,199999)
|
||||
local level=math.random(1,9)
|
||||
local memlevel=math.random(1,8)
|
||||
print("gzip: original size "..#s)
|
||||
print("gzip: cut point "..(v+1))
|
||||
print("gzip: level "..level)
|
||||
print("gzip: memlevel "..memlevel)
|
||||
local gz = gzip_init(nil, level, memlevel)
|
||||
local zip = gzip_deflate(gz,string.sub(s,1,v))
|
||||
zip = zip..gzip_deflate(gz,string.sub(s,v+1))
|
||||
zip = zip..gzip_deflate(gz,nil) -- finalize
|
||||
gzip_end(gz)
|
||||
print("gzip: deflated size "..#zip)
|
||||
local v=math.random(2,#zip-1)
|
||||
print("gunzip: cut point "..(v+1))
|
||||
gz = gunzip_init()
|
||||
local unzip = gunzip_inflate(gz,string.sub(zip,1,v))
|
||||
unzip = unzip..gunzip_inflate(gz,string.sub(zip,v+1))
|
||||
gunzip_end(gz)
|
||||
print("gunzip: inflated size "..#unzip)
|
||||
print("gzip+gunzip: "..(s==unzip and "OK" or "FAIL"))
|
||||
test_assert(s==unzip)
|
||||
end
|
||||
|
||||
function test_ipstr()
|
||||
print("* ipstr")
|
||||
|
||||
local s_ip, ip, s_ip2
|
||||
|
||||
s_ip = string.format("%u.%u.%u.%u", math.random(0,255), math.random(0,255), math.random(0,255), math.random(0,255));
|
||||
s_ip = string.format("%u.%u.%u.%u", math.random(0,255), math.random(0,255), math.random(0,255), math.random(0,255))
|
||||
ip = pton(s_ip)
|
||||
s_ip2 = ntop(ip)
|
||||
print("IP: "..s_ip)
|
||||
@@ -339,7 +494,7 @@ function test_ipstr()
|
||||
print("IP2: "..s_ip2)
|
||||
test_assert(s_ip==s_ip2)
|
||||
|
||||
s_ip = string.format("%x:%x:%x:%x:%x:%x:%x:%x", math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF));
|
||||
s_ip = string.format("%x:%x:%x:%x:%x:%x:%x:%x", math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF), math.random(1,0xFFFF))
|
||||
ip = pton(s_ip)
|
||||
s_ip2 = ntop(ip)
|
||||
print("IP: "..s_ip)
|
||||
@@ -350,6 +505,8 @@ end
|
||||
|
||||
|
||||
function test_dissect()
|
||||
print("* dissect")
|
||||
|
||||
local dis, raw1, raw2
|
||||
|
||||
for i=1,20 do
|
||||
@@ -387,13 +544,56 @@ function test_dissect()
|
||||
}
|
||||
raw1 = reconstruct_dissect(ip_tcp)
|
||||
print("IP+TCP : "..string2hex(raw1))
|
||||
dis1 = dissect(raw1);
|
||||
dis1 = dissect(raw1)
|
||||
raw2 = reconstruct_dissect(dis1)
|
||||
dis2 = dissect(raw2);
|
||||
dis2 = dissect(raw2)
|
||||
print("IP+TCP2: "..string2hex(raw2))
|
||||
print( raw1==raw2 and "DISSECT OK" or "DISSECT FAILED" )
|
||||
test_assert(raw1==raw2)
|
||||
|
||||
print("IP standalone")
|
||||
raw1 = reconstruct_iphdr(ip_tcp.ip)
|
||||
print("IP1: "..string2hex(raw1))
|
||||
dis1 = dissect_iphdr(raw1)
|
||||
raw2 = reconstruct_iphdr(dis1)
|
||||
print("IP2: "..string2hex(raw2))
|
||||
print( raw1==raw2 and "DISSECT OK" or "DISSECT FAILED" )
|
||||
test_assert(raw1==raw2)
|
||||
|
||||
print("TCP standalone")
|
||||
raw1 = reconstruct_tcphdr(ip_tcp.tcp)
|
||||
print("TCP1: "..string2hex(raw1))
|
||||
dis1 = dissect_tcphdr(raw1)
|
||||
raw2 = reconstruct_tcphdr(dis1)
|
||||
print("TCP2: "..string2hex(raw2))
|
||||
print( raw1==raw2 and "DISSECT OK" or "DISSECT FAILED" )
|
||||
test_assert(raw1==raw2)
|
||||
|
||||
local ip_icmp = {
|
||||
ip = {
|
||||
ip_tos = math.random(0,255),
|
||||
ip_id = math.random(0,0xFFFF),
|
||||
ip_off = 0,
|
||||
ip_ttl = math.random(0,255),
|
||||
ip_p = IPPROTO_ICMP,
|
||||
ip_src = brandom(4),
|
||||
ip_dst = brandom(4),
|
||||
options = brandom(math.random(0,40))
|
||||
},
|
||||
icmp = {
|
||||
icmp_type = ICMP_DEST_UNREACH, icmp_code=ICMP_UNREACH_PORT,
|
||||
icmp_data = math.random(1,0xFFFFFFFF)
|
||||
}
|
||||
}
|
||||
print("ICMP standalone")
|
||||
raw1 = reconstruct_icmphdr(ip_icmp.icmp)
|
||||
print("ICMP1: "..string2hex(raw1))
|
||||
dis1 = dissect_icmphdr(raw1)
|
||||
raw2 = reconstruct_icmphdr(dis1)
|
||||
print("ICMP2: "..string2hex(raw2))
|
||||
print( raw1==raw2 and "DISSECT OK" or "DISSECT FAILED" )
|
||||
test_assert(raw1==raw2)
|
||||
|
||||
local ip6_udp = {
|
||||
ip6 = {
|
||||
ip6_flow = 0x60000000 + math.random(0,0xFFFFFFF),
|
||||
@@ -414,18 +614,56 @@ function test_dissect()
|
||||
|
||||
raw1 = reconstruct_dissect(ip6_udp)
|
||||
print("IP6+UDP : "..string2hex(raw1))
|
||||
dis1 = dissect(raw1);
|
||||
dis1 = dissect(raw1)
|
||||
raw2 = reconstruct_dissect(dis1)
|
||||
dis2 = dissect(raw2);
|
||||
dis2 = dissect(raw2)
|
||||
print("IP6+UDP2: "..string2hex(raw2))
|
||||
print( raw1==raw2 and "DISSECT OK" or "DISSECT FAILED" )
|
||||
test_assert(raw1==raw2)
|
||||
|
||||
raw1 = string.sub(reconstruct_dissect(ip6_udp),1,-4-#ip6_udp.payload)
|
||||
dis1 = dissect(raw1, false)
|
||||
dis2 = dissect(raw1, true)
|
||||
local ok = not dis1.ip6 and dis2.ip6
|
||||
print("IP6 partial : "..(ok and "OK" or "FAIL"))
|
||||
test_assert(ok)
|
||||
|
||||
print("IP6+IPP")
|
||||
dis1 = {ip6 = ip6_udp.ip6, payload=brandom(math.random(1,1))}
|
||||
raw1 = reconstruct_dissect(dis1,{ip6_last_proto=IPPROTO_IPIP})
|
||||
dis2 = dissect(raw1)
|
||||
raw2 = reconstruct_dissect(dis2,{ip6_preserve_next=true})
|
||||
print("IP6+IPP1: "..string2hex(raw1))
|
||||
print("IP6+IPP2: "..string2hex(raw2))
|
||||
print( raw1==raw2 and "DISSECT OK" or "DISSECT FAILED" )
|
||||
test_assert(raw1==raw2)
|
||||
|
||||
print("UDP standalone")
|
||||
raw1 = reconstruct_udphdr(ip6_udp.udp)
|
||||
print("UDP1: "..string2hex(raw1))
|
||||
dis1 = dissect_udphdr(raw1)
|
||||
raw2 = reconstruct_udphdr(dis1)
|
||||
print("UDP2: "..string2hex(raw2))
|
||||
print( raw1==raw2 and "DISSECT OK" or "DISSECT FAILED" )
|
||||
test_assert(raw1==raw2)
|
||||
|
||||
print("IP6 standalone")
|
||||
ip6_udp.ip6.ip6_plen = nil
|
||||
raw1 = reconstruct_ip6hdr(ip6_udp.ip6,{ip6_last_proto=IPPROTO_UDP})
|
||||
print("IP1: "..string2hex(raw1))
|
||||
dis1 = dissect_ip6hdr(raw1)
|
||||
raw2 = reconstruct_ip6hdr(dis1,{ip6_last_proto=IPPROTO_UDP})
|
||||
print("IP2: "..string2hex(raw2))
|
||||
print( raw1==raw2 and "DISSECT OK" or "DISSECT FAILED" )
|
||||
test_assert(raw1==raw2)
|
||||
end
|
||||
end
|
||||
|
||||
function test_csum()
|
||||
print("* csum")
|
||||
|
||||
local payload = brandom(math.random(10,20))
|
||||
local ip4b, ip6b, raw, tcpb, udpb, dis1, dis2
|
||||
local ip4b, ip6b, raw, tcpb, udpb, icmpb, dis1, dis2
|
||||
local ip = {
|
||||
ip_tos = math.random(0,255),
|
||||
ip_id = math.random(0,0xFFFF),
|
||||
@@ -491,6 +729,8 @@ function test_csum()
|
||||
|
||||
raw = reconstruct_dissect({ip=ip, tcp=tcp, payload=payload})
|
||||
dis1 = dissect(raw)
|
||||
ip.ip_len = IP_BASE_LEN + #ip.options + #tcpb + #payload
|
||||
ip4b = reconstruct_iphdr(ip)
|
||||
tcpb = csum_tcp_fix(ip4b,tcpb,payload)
|
||||
dis2 = dissect(ip4b..tcpb..payload)
|
||||
print( dis1.tcp.th_sum==dis2.tcp.th_sum and "TCP+IP4 CSUM OK" or "TCP+IP4 CSUM FAILED" )
|
||||
@@ -526,18 +766,17 @@ function test_csum()
|
||||
print( dis1.tcp.th_sum==dis2.tcp.th_sum and "TCP+IP6 CSUM OK" or "TCP+IP6 CSUM FAILED" )
|
||||
test_assert(dis1.tcp.th_sum==dis2.tcp.th_sum)
|
||||
|
||||
|
||||
ip.ip_p = IPPROTO_UDP
|
||||
ip4b = reconstruct_iphdr(ip)
|
||||
ip6.ip6_plen = packet_len({ip6=ip6,udp=udp,payload=payload}) - IP6_BASE_LEN
|
||||
ip6b = reconstruct_ip6hdr(ip6, {ip6_last_proto=IPPROTO_UDP})
|
||||
|
||||
local udp = {
|
||||
uh_sport = math.random(0,0xFFFF),
|
||||
uh_dport = math.random(0,0xFFFF),
|
||||
uh_ulen = UDP_BASE_LEN + #payload
|
||||
}
|
||||
|
||||
ip.ip_p = IPPROTO_UDP
|
||||
ip4b = reconstruct_iphdr(ip)
|
||||
ip6.ip6_plen = packet_len({ip6=ip6,udp=udp,payload=payload}) - IP6_BASE_LEN
|
||||
ip6b = reconstruct_ip6hdr(ip6, {ip6_last_proto=IPPROTO_UDP})
|
||||
|
||||
udpb = reconstruct_udphdr(udp)
|
||||
raw = bu16(udp.uh_sport) ..
|
||||
bu16(udp.uh_dport) ..
|
||||
@@ -548,6 +787,8 @@ function test_csum()
|
||||
|
||||
raw = reconstruct_dissect({ip=ip, udp=udp, payload=payload})
|
||||
dis1 = dissect(raw)
|
||||
ip.ip_len = IP_BASE_LEN + #ip.options + #udpb + #payload
|
||||
ip4b = reconstruct_iphdr(ip)
|
||||
udpb = csum_udp_fix(ip4b,udpb,payload)
|
||||
dis2 = dissect(ip4b..udpb..payload)
|
||||
print( dis1.udp.uh_sum==dis2.udp.uh_sum and "UDP+IP4 CSUM OK" or "UDP+IP4 CSUM FAILED" )
|
||||
@@ -559,33 +800,117 @@ function test_csum()
|
||||
dis2 = dissect(ip6b..udpb..payload)
|
||||
print( dis1.udp.uh_sum==dis2.udp.uh_sum and "UDP+IP6 CSUM OK" or "UDP+IP6 CSUM FAILED" )
|
||||
test_assert(dis1.udp.uh_sum==dis2.udp.uh_sum)
|
||||
|
||||
local icmp = {
|
||||
icmp_type = math.random(0,0xFF), icmp_code=math.random(0,0xFF),
|
||||
icmp_data = math.random(0,0xFFFFFFFF)
|
||||
}
|
||||
ip.ip_p = IPPROTO_ICMP
|
||||
ip4b = reconstruct_iphdr(ip)
|
||||
ip6.ip6_plen = packet_len({ip6=ip6,icmp=icmp,payload=payload}) - IP6_BASE_LEN
|
||||
ip6b = reconstruct_ip6hdr(ip6, {ip6_last_proto=IPPROTO_ICMPV6})
|
||||
|
||||
icmpb = reconstruct_icmphdr(icmp)
|
||||
raw = bu8(icmp.icmp_type) ..
|
||||
bu8(icmp.icmp_code) ..
|
||||
bu16(0) ..
|
||||
bu32(icmp.icmp_data)
|
||||
print( raw==icmpb and "ICMP RECONSTRUCT OK" or "ICMP RECONSTRUCT FAILED" )
|
||||
test_assert(raw==icmpb)
|
||||
|
||||
raw = reconstruct_dissect({ip=ip, icmp=icmp, payload=payload})
|
||||
dis1 = dissect(raw)
|
||||
icmpb = csum_icmp_fix(ip4b,icmpb,payload)
|
||||
dis2 = dissect(ip4b..icmpb..payload)
|
||||
print( dis1.icmp.icmp_cksum==dis2.icmp.icmp_cksum and "ICMP+IP4 CSUM OK" or "ICMP+IP4 CSUM FAILED" )
|
||||
test_assert(dis1.icmp.icmp_cksum==dis2.icmp.icmp_cksum)
|
||||
|
||||
raw = reconstruct_dissect({ip6=ip6, icmp=icmp, payload=payload})
|
||||
dis1 = dissect(raw)
|
||||
icmpb = csum_icmp_fix(ip6b,icmpb,payload)
|
||||
dis2 = dissect(ip6b..icmpb..payload)
|
||||
print( dis1.icmp.icmp_cksum==dis2.icmp.icmp_cksum and "ICMP+IP6 CSUM OK" or "ICMP+IP6 CSUM FAILED" )
|
||||
test_assert(dis1.icmp.icmp_cksum==dis2.icmp.icmp_cksum)
|
||||
end
|
||||
|
||||
function test_resolve()
|
||||
print("* resolve")
|
||||
|
||||
local pos
|
||||
|
||||
pos = zero_based_pos(resolve_multi_pos(fake_default_tls,"tls_client_hello","1,extlen,sniext,host,sld,midsld,endsld,endhost,-5"))
|
||||
local tdis = tls_dissect(fake_default_tls)
|
||||
local extlen_pos = 5 + 6 + 32 + 1 + 2 + 1 + #tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.session_id + #tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.cipher_suites*2 + #tdis.handshake[TLS_HANDSHAKE_TYPE_CLIENT].dis.compression_methods
|
||||
print("fake_default_tls size "..#fake_default_tls.." extlen="..extlen_pos)
|
||||
local m="1,extlen,sniext,host,sld,midsld,endsld,endhost,-5"
|
||||
pos = resolve_multi_pos(fake_default_tls,"tls_client_hello",m,true)
|
||||
test_assert(pos)
|
||||
print("resolve_multi_pos tls : "..table.concat(pos," "))
|
||||
pos = zero_based_pos(resolve_range(fake_default_tls,"tls_client_hello","host,endhost"))
|
||||
print("resolve_multi_pos tls : "..m.." : "..table.concat(pos," "))
|
||||
m = "host,endhost"
|
||||
pos = resolve_range(fake_default_tls,"tls_client_hello",m,false,true)
|
||||
test_assert(pos)
|
||||
print("resolve_range tls : "..table.concat(pos," "))
|
||||
pos = resolve_pos(fake_default_tls,"tls_client_hello","midsld")
|
||||
print("resolve_range tls : "..m.." : "..table.concat(pos," "))
|
||||
m = "1"
|
||||
pos = resolve_pos(fake_default_tls,"tls_client_hello",m,true)
|
||||
test_assert(pos==1)
|
||||
print("resolve_pos tls : "..m.." : "..pos)
|
||||
m = "-1"
|
||||
pos = resolve_pos(fake_default_tls,"tls_client_hello",m,true)
|
||||
test_assert(pos==(#fake_default_tls-1))
|
||||
print("resolve_pos tls : "..m.." : "..pos)
|
||||
m = "extlen"
|
||||
pos = resolve_pos(fake_default_tls,"tls_client_hello",m,true)
|
||||
test_assert(pos==extlen_pos)
|
||||
print("resolve_pos tls : "..m.." : "..pos)
|
||||
m = "midsld"
|
||||
pos = resolve_pos(fake_default_tls,"tls_client_hello",m,true)
|
||||
test_assert(pos)
|
||||
print("resolve_pos tls : "..pos - 1)
|
||||
pos = resolve_pos(fake_default_tls,"tls_client_hello","method")
|
||||
print("resolve_pos tls : "..m.." : "..pos)
|
||||
m = "method"
|
||||
pos = resolve_pos(fake_default_tls,"tls_client_hello",m,true)
|
||||
test_assert(not pos)
|
||||
print("resolve_pos tls non-existent : "..tostring(pos))
|
||||
print("resolve_pos tls non-existent : "..m.." : "..tostring(pos))
|
||||
|
||||
pos = zero_based_pos(resolve_multi_pos(fake_default_http,"http_req","method,host,sld,midsld,endsld,endhost,-5"))
|
||||
local host_pos = string.find(fake_default_http,"Host: ")+6-1
|
||||
print("fake_default_http size "..#fake_default_http.." host="..host_pos)
|
||||
m = "method,host,sld,midsld,endsld,endhost,-5"
|
||||
pos = resolve_multi_pos(fake_default_http,"http_req",m,true)
|
||||
test_assert(pos)
|
||||
print("resolve_multi_pos http : "..table.concat(pos," "))
|
||||
pos = resolve_pos(fake_default_http,"http_req","sniext")
|
||||
test_assert(pos[1]==0)
|
||||
test_assert(pos[2]==host_pos)
|
||||
print("resolve_multi_pos http : "..m.." : "..table.concat(pos," "))
|
||||
m = "sniext"
|
||||
pos = resolve_pos(fake_default_http,"http_req",m,true)
|
||||
test_assert(not pos)
|
||||
print("resolve_pos http non-existent : "..tostring(pos))
|
||||
print("resolve_pos http non-existent : "..m.." : "..tostring(pos))
|
||||
end
|
||||
|
||||
function test_get_source_ip(opts)
|
||||
print("* get_source_ip")
|
||||
|
||||
for k,d in ipairs({
|
||||
'127.0.0.1','192.168.1.1','10.1.1.1','1.1.1.1','255.255.255.255',
|
||||
'::1','fc81::4','2a06::1','2001:470::1','2002:0101:0101::1','::1.1.1.1'})
|
||||
do
|
||||
local src = get_source_ip(pton(d))
|
||||
print((src and ntop(src) or "?").." => "..d)
|
||||
end
|
||||
end
|
||||
function test_ifaddrs(opts)
|
||||
print("* ifaddrs")
|
||||
|
||||
local ifa = get_ifaddrs()
|
||||
test_assert(ifa)
|
||||
for ifname,ifinfo in pairs(ifa) do
|
||||
print(ifname.." index="..tostring(ifinfo.index).." mtu="..tostring(ifinfo.mtu))
|
||||
for i,addr in ipairs(ifinfo.addr) do
|
||||
print(" "..ntop(addr.addr)..(addr.netmask and " mask "..tostring(ntop(addr.netmask)) or ""))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function test_rawsend(opts)
|
||||
print("* rawsend")
|
||||
|
||||
local ifout = (opts and opts.ifout) and opts.ifout
|
||||
local function rawsend_fail_warning()
|
||||
if not opts or not opts.ifout or #opts.ifout==0 then
|
||||
@@ -595,13 +920,13 @@ function test_rawsend(opts)
|
||||
end
|
||||
end
|
||||
end
|
||||
local function rawsend_dissect_print(dis, options)
|
||||
local function rawsend_dissect_print(dis, options, reconstruct)
|
||||
if options then
|
||||
options.ifout = ifout
|
||||
else
|
||||
options = { ifout = ifout }
|
||||
end
|
||||
local b = rawsend_dissect(dis, options)
|
||||
local b = rawsend_dissect(dis, options, reconstruct)
|
||||
if not b then
|
||||
print("rawsend_dissect failed")
|
||||
rawsend_fail_warning()
|
||||
@@ -626,15 +951,30 @@ function test_rawsend(opts)
|
||||
local payload = brandom(math.random(100,1200))
|
||||
local b
|
||||
|
||||
local target
|
||||
for ifname,ifinfo in pairs(get_ifaddrs()) do
|
||||
for k,v in pairs(ifinfo.addr) do
|
||||
if #v.addr==4 and string.sub(v.addr,1,2)=="\xC0\xA8" then
|
||||
target = string.sub(v.addr,1,3)..bu8(u8add(u8(v.addr,4),1))
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
target = target or pton("192.168.254.32")
|
||||
print("ipv4 target is "..ntop(target))
|
||||
ip = {
|
||||
ip_tos = 0,
|
||||
ip_id = math.random(0,0xFFFF),
|
||||
ip_off = 0,
|
||||
ip_ttl = 1,
|
||||
ip_p = IPPROTO_UDP,
|
||||
ip_src = pton("192.168.1.1"),
|
||||
ip_dst = pton("192.168.1.2")
|
||||
ip_src = get_source_ip(target),
|
||||
ip_dst = target
|
||||
}
|
||||
if not ip.ip_src then
|
||||
print("dest "..ntop(target).." unreachable")
|
||||
test_assert(false)
|
||||
end
|
||||
udp = {
|
||||
uh_sport = math.random(0,0xFFFF),
|
||||
uh_dport = math.random(0,0xFFFF)
|
||||
@@ -657,18 +997,42 @@ function test_rawsend(opts)
|
||||
print("send ipv4 udp using pure rawsend without dissect")
|
||||
test_assert(rawsend_print(raw, {repeats=5}))
|
||||
|
||||
local target
|
||||
for ifname,ifinfo in pairs(get_ifaddrs()) do
|
||||
for k,v in pairs(ifinfo.addr) do
|
||||
if #v.addr==16 and (string.sub(v.addr,1,1)=="\xFC" or string.sub(v.addr,1,1)=="\xFD") then
|
||||
target = string.sub(v.addr,1,1)..bu8(u8add(u8(v.addr,2),1))..string.sub(v.addr,3)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
target = target or pton("fdce:3124:164a:5318::2")
|
||||
print("ipv6 target is "..ntop(target))
|
||||
ip6 = {
|
||||
ip6_flow = 0x60000000,
|
||||
ip6_hlim = 1,
|
||||
ip6_src = pton("fdce:3124:164a:5318::1"),
|
||||
ip6_dst = pton("fdce:3124:164a:5318::2")
|
||||
ip6_src = get_source_ip(target),
|
||||
ip6_dst = target
|
||||
}
|
||||
if not ip6.ip6_src then
|
||||
print("dest "..ntop(target).." unreachable")
|
||||
test_assert(false)
|
||||
end
|
||||
dis = {ip6 = ip6, udp = udp, payload = payload}
|
||||
print("send ipv6 udp")
|
||||
test_assert(rawsend_dissect_print(dis, {repeats=3}))
|
||||
|
||||
ip2 = deepcopy(ip6)
|
||||
ip2.ip6_plen = UDP_BASE_LEN + #payload
|
||||
raw_ip = reconstruct_ip6hdr(ip2, {ip6_last_proto = IPPROTO_UDP})
|
||||
raw_udp = reconstruct_udphdr({uh_sport = udp.uh_sport, uh_dport = udp.uh_dport, uh_ulen = UDP_BASE_LEN + #payload})
|
||||
raw_udp = csum_udp_fix(raw_ip,raw_udp,payload)
|
||||
raw = raw_ip .. raw_udp .. payload
|
||||
print("send ipv6 udp using pure rawsend without dissect")
|
||||
test_assert(rawsend_print(raw, {repeats=7}))
|
||||
|
||||
ddis = ipfrag2(dis, {ipfrag_pos_udp = 80})
|
||||
for k,d in pairs(ddis) do
|
||||
for k,d in ipairs(ddis) do
|
||||
print("send ipv6 udp frag "..k)
|
||||
test_assert(rawsend_dissect_print(d))
|
||||
end
|
||||
@@ -678,27 +1042,67 @@ function test_rawsend(opts)
|
||||
test_assert(rawsend_dissect_print(dis, {repeats=3}))
|
||||
|
||||
ddis = ipfrag2(dis, {ipfrag_pos_udp = 80})
|
||||
for k,d in pairs(ddis) do
|
||||
for k,d in ipairs(ddis) do
|
||||
print("send ipv6 udp frag "..k.." with hopbyhop ext header")
|
||||
test_assert(rawsend_dissect_print(d))
|
||||
end
|
||||
|
||||
table.insert(ip6.exthdr, { type = IPPROTO_DSTOPTS, data = "\x00\x00\x00\x00\x00\x00" })
|
||||
table.insert(ip6.exthdr, { type = IPPROTO_DSTOPTS, data = "\x00\x00\x00\x00\x00\x00" })
|
||||
ip6.ip6_flow = 0x60001234;
|
||||
insert_ip6_exthdr(ip6, nil, IPPROTO_DSTOPTS, "\x00\x00\x00\x00\x00\x00")
|
||||
insert_ip6_exthdr(ip6, nil, IPPROTO_DSTOPTS, "\x00\x00\x00\x00\x00\x00")
|
||||
ip6.ip6_flow = 0x60001234
|
||||
ddis = ipfrag2(dis, {ipfrag_pos_udp = 80})
|
||||
for k,d in pairs(ddis) do
|
||||
for k,d in ipairs(ddis) do
|
||||
print("send ipv6 udp frag "..k.." with hopbyhop, destopt ext headers in unfragmentable part and another destopt ext header in fragmentable part")
|
||||
test_assert(rawsend_dissect_print(d, {fwmark = 0x50EA}))
|
||||
end
|
||||
|
||||
fix_ip6_next(ip6) -- required to forge next proto in the second fragment
|
||||
ip6.ip6_flow = 0x6000AE38;
|
||||
ddis = ipfrag2(dis, {ipfrag_pos_udp = 80, ipfrag_next = IPPROTO_TCP})
|
||||
for k,d in pairs(ddis) do
|
||||
fix_ip_proto(dis) -- ip6_preserve_next requires next fields in ip6.exthdr
|
||||
ip6.ip6_flow = 0x6000AE38
|
||||
ddis = ipfrag2(dis, {ipfrag_pos_udp = 72, ipfrag_next = IPPROTO_TCP})
|
||||
for k,d in ipairs(ddis) do
|
||||
print("send ipv6 udp frag "..k.." with hopbyhop, destopt ext headers in unfragmentable part and another destopt ext header in fragmentable part. forge next proto in fragment header of the second fragment to TCP")
|
||||
-- reconstruct dissect using next proto fields in the dissect. do not auto fix next proto chain.
|
||||
-- by default reconstruct fixes next proto chain
|
||||
test_assert(rawsend_dissect_print(d, {fwmark = 0x409A, repeats=2}, {ip6_preserve_next = true}))
|
||||
end
|
||||
|
||||
local icmp = {
|
||||
icmp_type = ICMP_ECHO, icmp_code=0,
|
||||
icmp_data = u32(bu16(math.random(1,0xFFFF))..bu16(1))
|
||||
}
|
||||
ip.ip_p = IPPROTO_ICMP
|
||||
payload=brandom_az09(math.random(10,1100))
|
||||
dis = {ip = ip, icmp = icmp, payload = payload}
|
||||
print("send ipv4 icmp")
|
||||
test_assert(rawsend_dissect_print(dis, {fwmark = 0xD133, repeats=3}))
|
||||
|
||||
ip6.exthdr={{ type = IPPROTO_HOPOPTS, data = "\x00\x00\x00\x00\x00\x00" }}
|
||||
ip6.ip6_flow=0x60009E3B
|
||||
icmp.icmp_type = ICMP6_ECHO_REQUEST
|
||||
dis = {ip6 = ip6, icmp = icmp, payload = payload}
|
||||
print("send ipv6 icmp")
|
||||
test_assert(rawsend_dissect_print(dis, {fwmark = 0x8E10, repeats=3}))
|
||||
|
||||
local ip2 = {
|
||||
ip_tos = 0,
|
||||
ip_id = math.random(0,0xFFFF),
|
||||
ip_off = 0,
|
||||
ip_ttl = 64,
|
||||
ip_p = IPPROTO_UDP,
|
||||
ip_src = pton("10.1.1.1"),
|
||||
ip_dst = pton("10.1.1.2"),
|
||||
}
|
||||
|
||||
dis = {ip = ip2, udp = udp, payload = payload}
|
||||
raw_udp = reconstruct_dissect(dis)
|
||||
|
||||
ip6.ip6_flow=0x6000583F
|
||||
dis = {ip6 = ip6, payload = raw_udp}
|
||||
print("send ipv6 ipip")
|
||||
test_assert(rawsend_dissect_print(dis, {fwmark = 0x8E10, repeats=3}, {ip6_last_proto=IPPROTO_IPIP}))
|
||||
|
||||
dis = {ip = ip, payload = raw_udp}
|
||||
dis.ip.ip_p = IPPROTO_IPIP
|
||||
print("send ipv4 ipip")
|
||||
test_assert(rawsend_dissect_print(dis, {fwmark = 0x8E10, repeats=3}, {ip6_last_proto=IPPROTO_IPIP}))
|
||||
end
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
-- test case : nfqws2 --qnum 200 --debug --lua-init=@zapret-wgobfs.lua --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
|
||||
-- reduce MTU of wireguard interface to avoid ip fragmentation !
|
||||
-- without knowing the secret encrypted packets should be crypto strong white noise with no signature
|
||||
-- arg : secret - shared secret. any string. must be the same on both peers
|
||||
-- arg : padmin - min random garbage bytes. 0 by default
|
||||
-- arg : padmax - max random garbage bytes. 16 by default
|
||||
function wgobfs(ctx, desync)
|
||||
local padmin = desync.arg.padmin and tonumber(desync.arg.padmin) or 0
|
||||
local padmax = desync.arg.padmax and tonumber(desync.arg.padmax) or 16
|
||||
local function genkey()
|
||||
-- cache key in a global var bound to instance name
|
||||
local key_cache_name = desync.func_instance.."_key"
|
||||
key = _G[key_cache_name]
|
||||
if not key then
|
||||
key = hkdf("sha256", "wgobfs_salt", desync.arg.secret, nil, 16)
|
||||
_G[key_cache_name] = key
|
||||
end
|
||||
return key
|
||||
end
|
||||
local function maybe_encrypted_payload(payload)
|
||||
for k,plsize in pairs({2+12+16+148, 2+12+16+92, 2+12+16+64}) do
|
||||
if #payload>=(plsize+padmin) and #payload<=(plsize+padmax) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
local function wg_payload_from_size(payload)
|
||||
if #payload==148 then return "wireguard_initiation"
|
||||
elseif #payload==92 then return "wireguard_response"
|
||||
elseif #payload==64 then return "wireguard_cookie"
|
||||
else return nil
|
||||
end
|
||||
end
|
||||
|
||||
if not desync.dis.udp then
|
||||
instance_cutoff(ctx)
|
||||
return
|
||||
end
|
||||
if not desync.arg.secret or #desync.arg.secret==0 then
|
||||
error("wgobfs requires secret")
|
||||
end
|
||||
if padmin>padmax then
|
||||
error("wgobfs: padmin>padmax")
|
||||
end
|
||||
if desync.l7payload=="wireguard_initiation" or desync.l7payload=="wireguard_response" or desync.l7payload=="wireguard_cookie" and #desync.dis.payload<65506 then
|
||||
DLOG("wgobfs: encrypting '"..desync.l7payload.."'. size "..#desync.dis.payload)
|
||||
local key = genkey()
|
||||
-- in aes-gcm every message require it's own crypto secure random iv
|
||||
-- encrypting more than one message with the same iv is considered catastrophic failure
|
||||
-- iv must be sent with encrypted message
|
||||
local iv = bcryptorandom(12)
|
||||
local encrypted, atag = aes_gcm(true, key, iv, bu16(#desync.dis.payload)..desync.dis.payload..brandom(math.random(padmin,padmax)), nil)
|
||||
desync.dis.payload = iv..atag..encrypted
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
|
||||
if desync.l7payload=="unknown" and maybe_encrypted_payload(desync.dis.payload) then
|
||||
local key = genkey()
|
||||
local iv = string.sub(desync.dis.payload,1,12)
|
||||
local atag = string.sub(desync.dis.payload,13,28)
|
||||
local decrypted, atag2 = aes_gcm(false, key, iv, string.sub(desync.dis.payload,29))
|
||||
if atag==atag2 then
|
||||
local plen = u16(decrypted)
|
||||
if plen>(#decrypted-2) then
|
||||
DLOG("wgobfs: bad decrypted payload data")
|
||||
else
|
||||
desync.dis.payload = string.sub(decrypted, 3, 3+plen-1)
|
||||
if b_debug then DLOG("wgobfs: decrypted '"..(wg_payload_from_size(desync.dis.payload) or "unknown").."' message. size "..plen) end
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
else
|
||||
DLOG("wgobfs: decrypt auth tag mismatch")
|
||||
end
|
||||
end
|
||||
end
|
||||
60
mdig/mdig.c
60
mdig/mdig.c
@@ -30,7 +30,8 @@
|
||||
#endif
|
||||
#include <time.h>
|
||||
|
||||
#define RESOLVER_EAGAIN_ATTEMPTS 2
|
||||
#define RESOLVER_EAGAIN_ATTEMPTS 10
|
||||
#define RESOLVER_EAGAIN_DELAY 500
|
||||
|
||||
static void trimstr(char *s)
|
||||
{
|
||||
@@ -79,15 +80,15 @@ static bool dom_valid(char *dom)
|
||||
{
|
||||
if (!dom || *dom=='.') return false;
|
||||
for (; *dom; dom++)
|
||||
if (*dom < 0x20 || (*dom & 0x80) || !(*dom == '.' || *dom == '-' || *dom == '_' || (*dom >= '0' && *dom <= '9') || (*dom >= 'a' && *dom <= 'z') || (*dom >= 'A' && *dom <= 'Z')))
|
||||
return false;
|
||||
if (!(*dom == '.' || *dom == '-' || *dom == '_' || (*dom >= '0' && *dom <= '9') || (*dom >= 'a' && *dom <= 'z') || (*dom >= 'A' && *dom <= 'Z')))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void invalid_domain_beautify(char *dom)
|
||||
{
|
||||
for (int i = 0; *dom && i < 64; i++, dom++)
|
||||
if (*dom < 0x20 || *dom>0x7F) *dom = '?';
|
||||
if (*dom < 0x20 || (*dom & 0x80)) *dom = '?';
|
||||
if (*dom) *dom = 0;
|
||||
}
|
||||
|
||||
@@ -97,7 +98,7 @@ static struct
|
||||
{
|
||||
char verbose;
|
||||
char family;
|
||||
int threads;
|
||||
int threads, eagain, eagain_delay;
|
||||
time_t start_time;
|
||||
pthread_mutex_t flock;
|
||||
pthread_mutex_t slock; // stats lock
|
||||
@@ -193,11 +194,12 @@ static void *t_resolver(void *arg)
|
||||
int i, r;
|
||||
char dom[256];
|
||||
bool is_ok;
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result;
|
||||
struct addrinfo hints, *result;
|
||||
struct timespec ts_eagain = { .tv_sec = glob.eagain_delay/1000, .tv_nsec=glob.eagain_delay%1000*1000000 };
|
||||
|
||||
VLOG("started");
|
||||
|
||||
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = (glob.family == FAMILY4) ? AF_INET : (glob.family == FAMILY6) ? AF_INET6 : AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
@@ -218,7 +220,7 @@ static void *t_resolver(void *arg)
|
||||
{
|
||||
if ((family == AF_INET && (glob.family & FAMILY4)) || (family == AF_INET6 && (glob.family & FAMILY6)))
|
||||
{
|
||||
unsigned int mask;
|
||||
unsigned int mask=0;
|
||||
bool mask_needed = false;
|
||||
if (s_mask)
|
||||
{
|
||||
@@ -244,12 +246,16 @@ static void *t_resolver(void *arg)
|
||||
else if (dom_valid(dom))
|
||||
{
|
||||
VLOG("resolving %s", dom);
|
||||
for (i = 0; i < RESOLVER_EAGAIN_ATTEMPTS; i++)
|
||||
for (i = 0; i < glob.eagain; i++)
|
||||
{
|
||||
if ((r = getaddrinfo(dom, NULL, &hints, &result)))
|
||||
{
|
||||
VLOG("failed to resolve %s : result %d (%s)", dom, r, eai_str(r));
|
||||
if (r == EAI_AGAIN) continue; // temporary failure. should retry
|
||||
if (r == EAI_AGAIN)
|
||||
{
|
||||
nanosleep(&ts_eagain, NULL);
|
||||
continue; // temporary failure. should retry
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -430,7 +436,7 @@ int dns_parse_query()
|
||||
_setmode(_fileno(stdin), _O_BINARY);
|
||||
#endif
|
||||
l = fread(a,1,sizeof(a),stdin);
|
||||
if (!l || !feof(stdin))
|
||||
if (!l || ferror(stdin))
|
||||
{
|
||||
fprintf(stderr, "could not read DNS reply blob from stdin\n");
|
||||
return 10;
|
||||
@@ -447,14 +453,18 @@ int dns_parse_query()
|
||||
static void exithelp(void)
|
||||
{
|
||||
printf(
|
||||
" --threads=<threads_number>\n"
|
||||
" --family=<4|6|46>\t\t; ipv4, ipv6, ipv4+ipv6\n"
|
||||
" --threads=<threads_number>\n"
|
||||
" --eagain=<eagain_retries>\t; how many times to retry if EAI_AGAIN received. default %u\n"
|
||||
" --eagain-delay=<ms>\t\t; time in msec to wait between EAI_AGAIN attempts. default %u\n"
|
||||
" --verbose\t\t\t; print query progress to stderr\n"
|
||||
" --stats=N\t\t\t; print resolve stats to stderr every N domains\n"
|
||||
" --log-resolved=<file>\t\t; log successfully resolved domains to a file\n"
|
||||
" --log-failed=<file>\t\t; log failed domains to a file\n"
|
||||
" --dns-make-query=<domain>\t; output to stdout binary blob with DNS query. use --family to specify ip version.\n"
|
||||
" --dns-parse-query\t\t; read from stdin binary DNS answer blob and parse it to ipv4/ipv6 addresses\n"
|
||||
" --dns-parse-query\t\t; read from stdin binary DNS answer blob and parse it to ipv4/ipv6 addresses\n",
|
||||
RESOLVER_EAGAIN_ATTEMPTS,
|
||||
RESOLVER_EAGAIN_DELAY
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
@@ -469,6 +479,8 @@ static void exithelp(void)
|
||||
|
||||
enum opt_indices {
|
||||
IDX_HELP,
|
||||
IDX_EAGAIN,
|
||||
IDX_EAGAIN_DELAY,
|
||||
IDX_THREADS,
|
||||
IDX_FAMILY,
|
||||
IDX_VERBOSE,
|
||||
@@ -483,6 +495,8 @@ enum opt_indices {
|
||||
static const struct option long_options[] = {
|
||||
[IDX_HELP] = {"help", no_argument, 0, 0},
|
||||
[IDX_THREADS] = {"threads", required_argument, 0, 0},
|
||||
[IDX_EAGAIN] = {"eagain", required_argument, 0, 0},
|
||||
[IDX_EAGAIN_DELAY] = {"eagain-delay", required_argument, 0, 0},
|
||||
[IDX_FAMILY] = {"family", required_argument, 0, 0},
|
||||
[IDX_VERBOSE] = {"verbose", no_argument, 0, 0},
|
||||
[IDX_STATS] = {"stats", required_argument, 0, 0},
|
||||
@@ -503,6 +517,8 @@ int main(int argc, char **argv)
|
||||
*fn1 = *fn2 = *dom = 0;
|
||||
glob.family = FAMILY4;
|
||||
glob.threads = 1;
|
||||
glob.eagain = RESOLVER_EAGAIN_ATTEMPTS;
|
||||
glob.eagain_delay = RESOLVER_EAGAIN_DELAY;
|
||||
while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
|
||||
{
|
||||
if (v) exithelp();
|
||||
@@ -513,13 +529,29 @@ int main(int argc, char **argv)
|
||||
exithelp();
|
||||
break;
|
||||
case IDX_THREADS:
|
||||
glob.threads = optarg ? atoi(optarg) : 0;
|
||||
glob.threads = atoi(optarg);
|
||||
if (glob.threads <= 0 || glob.threads > 100)
|
||||
{
|
||||
fprintf(stderr, "thread number must be within 1..100\n");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case IDX_EAGAIN:
|
||||
glob.eagain = atoi(optarg);
|
||||
if (glob.eagain <= 0 || glob.eagain > 1000)
|
||||
{
|
||||
fprintf(stderr, "eagain must be within 1..1000\n");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case IDX_EAGAIN_DELAY:
|
||||
glob.eagain_delay = atoi(optarg);
|
||||
if (glob.eagain_delay < 0 || glob.eagain_delay > 100000)
|
||||
{
|
||||
fprintf(stderr, "eagain-delay must be within 0..100000\n");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case IDX_FAMILY:
|
||||
if (!strcmp(optarg, "4"))
|
||||
glob.family = FAMILY4;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
CC ?= cc
|
||||
OPTIMIZE ?= -Os
|
||||
CFLAGS += -std=gnu99 -s $(OPTIMIZE) -flto=auto -Wno-address-of-packed-member
|
||||
PKG_CONFIG ?= pkg-config
|
||||
OPTIMIZE ?= -Oz
|
||||
MINSIZE ?= -flto=auto -ffunction-sections -fdata-sections
|
||||
CFLAGS += -std=gnu99 -s $(OPTIMIZE) $(MINSIZE) -Wno-address-of-packed-member
|
||||
LDFLAGS += -flto=auto -Wl,--gc-sections
|
||||
LIBS = -lz -lm
|
||||
SRC_FILES = *.c crypto/*.c
|
||||
|
||||
@@ -14,7 +17,7 @@ LUA_PKG:=luajit
|
||||
|
||||
.else
|
||||
|
||||
LUA_VER ?= 5.4
|
||||
LUA_VER ?= 5.5
|
||||
LUA_VER_UNDOTTED!= echo $(LUA_VER) | sed 's/\.//g'
|
||||
|
||||
OSNAME!=uname
|
||||
@@ -26,8 +29,8 @@ OSNAME!=uname
|
||||
|
||||
.endif
|
||||
|
||||
LUA_LIB!= pkg-config --libs $(LUA_PKG)
|
||||
LUA_CFLAGS!= pkg-config --cflags $(LUA_PKG)
|
||||
LUA_LIB!= $(PKG_CONFIG) --libs $(LUA_PKG)
|
||||
LUA_CFLAGS!= $(PKG_CONFIG) --cflags $(LUA_PKG)
|
||||
|
||||
.if "${LUA_JIT}" == "1"
|
||||
LUA_CFLAGS+=-DLUAJIT
|
||||
|
||||
@@ -1,21 +1,27 @@
|
||||
CC ?= cc
|
||||
PKG_CONFIG ?= pkg-config
|
||||
OPTIMIZE ?= -Os
|
||||
CFLAGS += -std=gnu99 $(OPTIMIZE) -flto=auto
|
||||
MINSIZE ?= -flto=auto -ffunction-sections -fdata-sections
|
||||
CFLAGS += -std=gnu99 $(OPTIMIZE) $(MINSIZE)
|
||||
CFLAGS_LINUX = -Wno-alloc-size-larger-than
|
||||
CFLAGS_SYSTEMD = -DUSE_SYSTEMD
|
||||
CFLAGS_BSD = -Wno-address-of-packed-member
|
||||
CFLAGS_CYGWIN = -Wno-address-of-packed-member -static
|
||||
CFLAGS_CYGWIN32 =
|
||||
CFLAGS_UBSAN = -fsanitize=undefined,alignment -fno-sanitize-recover=undefined,alignment
|
||||
LDFLAGS += -flto=auto -Wl,--gc-sections
|
||||
LDFLAGS_ANDROID = -llog
|
||||
LIBS =
|
||||
LIBS_LINUX = -lz -lnetfilter_queue -lnfnetlink -lmnl -lm
|
||||
LIBS_SYSTEMD = -lsystemd
|
||||
LIBS_BSD = -lz -lm
|
||||
LIBS_CYGWIN = -lz -Lwindows/windivert -Iwindows -lwlanapi -lole32 -loleaut32
|
||||
LIBS_CYGWIN = -lz -Lwindows/windivert -Iwindows -lole32 -loleaut32 -liphlpapi -lntdll
|
||||
LIBS_CYGWIN32 = -lwindivert32
|
||||
LIBS_CYGWIN64 = -lwindivert64
|
||||
RES_CYGWIN32 = windows/res/32/winmanifest.o windows/res/32/winicon.o
|
||||
RES_CYGWIN64 = windows/res/64/winmanifest.o windows/res/64/winicon.o
|
||||
RES_CYGWIN32 = windows/res/winws_res32.o
|
||||
RES_CYGWIN64 = windows/res/winws_res64.o
|
||||
SRC_FILES = *.c crypto/*.c
|
||||
|
||||
SRC_FILES_ANDROID = $(SRC_FILES) andr/*.c
|
||||
|
||||
LUA_JIT?=1
|
||||
|
||||
@@ -24,18 +30,19 @@ ifeq ($(LUA_JIT),1)
|
||||
LUAJIT_VER?=2.1
|
||||
LUAJIT_LUA_VER?=5.1
|
||||
LUA_PKG:=luajit
|
||||
CFLAGS_CYGWIN32 = -msse2 -mfpmath=sse
|
||||
|
||||
$(info trying luajit $(LUAJIT_VER) lua $(LUAJIT_LUA_VER))
|
||||
|
||||
LUA_LIB_NAME=
|
||||
ifeq ($(LUA_CFLAGS),)
|
||||
LUA_CFLAGS := $(shell pkg-config --cflags $(LUA_PKG) 2>/dev/null)
|
||||
LUA_CFLAGS := $(shell $(PKG_CONFIG) --cflags $(LUA_PKG) 2>/dev/null)
|
||||
ifeq ($(LUA_CFLAGS),)
|
||||
LUA_CFLAGS := -I/usr/local/include/luajit-$(LUAJIT_VER) -I/usr/include/luajit-$(LUAJIT_VER)
|
||||
endif
|
||||
endif
|
||||
ifeq ($(LUA_LIB),)
|
||||
LUA_LIB := $(shell pkg-config --libs $(LUA_PKG) 2>/dev/null)
|
||||
LUA_LIB := $(shell $(PKG_CONFIG) --libs $(LUA_PKG) 2>/dev/null)
|
||||
LUA_LIB_DIR :=
|
||||
|
||||
ifeq ($(LUA_LIB),)
|
||||
@@ -72,7 +79,7 @@ ifeq ($(LUA_LIB),)
|
||||
|
||||
# no success with luajit
|
||||
|
||||
LUA_VER?=5.4
|
||||
LUA_VER?=5.5
|
||||
LUA_VER_UNDOTTED:=$(shell echo $(LUA_VER) | sed 's/\.//g')
|
||||
|
||||
LUA_CFL :=
|
||||
@@ -87,13 +94,13 @@ else
|
||||
endif
|
||||
|
||||
ifeq ($(LUA_CFLAGS),)
|
||||
LUA_CFLAGS := $(shell pkg-config --cflags $(LUA_PKG) 2>/dev/null)
|
||||
LUA_CFLAGS := $(shell $(PKG_CONFIG) --cflags $(LUA_PKG) 2>/dev/null)
|
||||
ifeq ($(LUA_CFLAGS),)
|
||||
LUA_CFLAGS := -I/usr/local/include/lua$(LUA_VER) -I/usr/local/include/lua-$(LUA_VER) -I/usr/include/lua$(LUA_VER) -I/usr/include/lua-$(LUA_VER)
|
||||
LUA_CFLAGS := -I/usr/local/include/lua$(LUA_VER) -I/usr/local/include/lua-$(LUA_VER) -I/usr/include/lua$(LUA_VER) -I/usr/include/lua-$(LUA_VER) -I/usr/local/include/lua -I/usr/local/include
|
||||
endif
|
||||
endif
|
||||
ifeq ($(LUA_LIB),)
|
||||
LUA_LIB := $(shell pkg-config --libs $(LUA_PKG) 2>/dev/null)
|
||||
LUA_LIB := $(shell $(PKG_CONFIG) --libs $(LUA_PKG) 2>/dev/null)
|
||||
LUA_LIB_DIR :=
|
||||
ifeq ($(LUA_LIB),)
|
||||
ifneq ($(wildcard /usr/local/lib/liblua-$(LUA_VER).*),)
|
||||
@@ -131,21 +138,24 @@ LUA_CFL += $(LUA_CFLAGS)
|
||||
all: nfqws2
|
||||
|
||||
nfqws2: $(SRC_FILES)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LDFLAGS)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_LINUX) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LDFLAGS)
|
||||
|
||||
ubsan: $(SRC_FILES)
|
||||
$(CC) $(CFLAGS_UBSAN) $(CFLAGS) $(LUA_CFL) $(CFLAGS_LINUX) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LDFLAGS)
|
||||
|
||||
systemd: $(SRC_FILES)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_SYSTEMD) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LIBS_SYSTEMD) $(LDFLAGS)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_LINUX) $(CFLAGS_SYSTEMD) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LIBS_SYSTEMD) $(LDFLAGS)
|
||||
|
||||
android: $(SRC_FILES)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) -o nfqws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LDFLAGS) $(LDFLAGS_ANDROID)
|
||||
android: $(SRC_FILES_ANDROID)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) -o nfqws2 $(SRC_FILES_ANDROID) $(LIBS) $(LUA_LIB) $(LIBS_LINUX) $(LDFLAGS) $(LDFLAGS_ANDROID)
|
||||
|
||||
bsd: $(SRC_FILES)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_BSD) -o dvtws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_BSD) $(LDFLAGS)
|
||||
|
||||
cygwin64:
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) -o winws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN64) $(RES_CYGWIN64) $(LDFLAGS)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) -o winws2 $(SRC_FILES) $(RES_CYGWIN64) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN64) $(LDFLAGS)
|
||||
cygwin32:
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) -o winws2 $(SRC_FILES) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN32) $(RES_CYGWIN32) $(LDFLAGS)
|
||||
$(CC) -s $(CFLAGS) $(LUA_CFL) $(CFLAGS_CYGWIN) $(CFLAGS_CYGWIN32) -o winws2 $(SRC_FILES) $(RES_CYGWIN32) $(LIBS) $(LUA_LIB) $(LIBS_CYGWIN) $(LIBS_CYGWIN32) $(LDFLAGS)
|
||||
cygwin: cygwin64
|
||||
|
||||
clean:
|
||||
|
||||
216
nfq2/andr/getifaddrs.c
Normal file
216
nfq2/andr/getifaddrs.c
Normal file
@@ -0,0 +1,216 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <syscall.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include "netlink.h"
|
||||
|
||||
#define IFADDRS_HASH_SIZE 64
|
||||
|
||||
/* getifaddrs() reports hardware addresses with PF_PACKET that implies
|
||||
* struct sockaddr_ll. But e.g. Infiniband socket address length is
|
||||
* longer than sockaddr_ll.ssl_addr[8] can hold. Use this hack struct
|
||||
* to extend ssl_addr - callers should be able to still use it. */
|
||||
struct sockaddr_ll_hack {
|
||||
unsigned short sll_family, sll_protocol;
|
||||
int sll_ifindex;
|
||||
unsigned short sll_hatype;
|
||||
unsigned char sll_pkttype, sll_halen;
|
||||
unsigned char sll_addr[24];
|
||||
};
|
||||
|
||||
union sockany {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_ll_hack ll;
|
||||
struct sockaddr_in v4;
|
||||
struct sockaddr_in6 v6;
|
||||
};
|
||||
|
||||
struct ifaddrs_storage {
|
||||
struct ifaddrs ifa;
|
||||
struct ifaddrs_storage *hash_next;
|
||||
union sockany addr, netmask, ifu;
|
||||
unsigned int index;
|
||||
char name[IFNAMSIZ+1];
|
||||
};
|
||||
|
||||
struct ifaddrs_ctx {
|
||||
struct ifaddrs *first;
|
||||
struct ifaddrs *last;
|
||||
struct ifaddrs_storage *hash[IFADDRS_HASH_SIZE];
|
||||
};
|
||||
|
||||
void freeifaddrs(struct ifaddrs *ifp)
|
||||
{
|
||||
struct ifaddrs *n;
|
||||
while (ifp) {
|
||||
n = ifp->ifa_next;
|
||||
free(ifp);
|
||||
ifp = n;
|
||||
}
|
||||
}
|
||||
|
||||
static void copy_addr(struct sockaddr **r, int af, union sockany *sa, void *addr, size_t addrlen, int ifindex)
|
||||
{
|
||||
uint8_t *dst;
|
||||
int len;
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
dst = (uint8_t*) &sa->v4.sin_addr;
|
||||
len = 4;
|
||||
break;
|
||||
case AF_INET6:
|
||||
dst = (uint8_t*) &sa->v6.sin6_addr;
|
||||
len = 16;
|
||||
if (IN6_IS_ADDR_LINKLOCAL(addr) || IN6_IS_ADDR_MC_LINKLOCAL(addr))
|
||||
sa->v6.sin6_scope_id = ifindex;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (addrlen < len) return;
|
||||
sa->sa.sa_family = af;
|
||||
memcpy(dst, addr, len);
|
||||
*r = &sa->sa;
|
||||
}
|
||||
|
||||
static void gen_netmask(struct sockaddr **r, int af, union sockany *sa, int prefixlen)
|
||||
{
|
||||
uint8_t addr[16] = {0};
|
||||
int i;
|
||||
|
||||
if (prefixlen > 8*sizeof(addr)) prefixlen = 8*sizeof(addr);
|
||||
i = prefixlen / 8;
|
||||
memset(addr, 0xff, i);
|
||||
if (i < sizeof(addr)) addr[i++] = 0xff << (8 - (prefixlen % 8));
|
||||
copy_addr(r, af, sa, addr, sizeof(addr), 0);
|
||||
}
|
||||
|
||||
static void copy_lladdr(struct sockaddr **r, union sockany *sa, void *addr, size_t addrlen, int ifindex, unsigned short hatype)
|
||||
{
|
||||
if (addrlen > sizeof(sa->ll.sll_addr)) return;
|
||||
sa->ll.sll_family = AF_PACKET;
|
||||
sa->ll.sll_ifindex = ifindex;
|
||||
sa->ll.sll_hatype = hatype;
|
||||
sa->ll.sll_halen = addrlen;
|
||||
memcpy(sa->ll.sll_addr, addr, addrlen);
|
||||
*r = &sa->sa;
|
||||
}
|
||||
|
||||
static int netlink_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
|
||||
{
|
||||
struct ifaddrs_ctx *ctx = pctx;
|
||||
struct ifaddrs_storage *ifs, *ifs0;
|
||||
struct ifinfomsg *ifi = NLMSG_DATA(h);
|
||||
struct ifaddrmsg *ifa = NLMSG_DATA(h);
|
||||
struct rtattr *rta;
|
||||
int stats_len = 0;
|
||||
|
||||
if (h->nlmsg_type == RTM_NEWLINK) {
|
||||
for (rta = NLMSG_RTA(h, sizeof(*ifi)); NLMSG_RTAOK(rta, h); rta = RTA_NEXT(rta)) {
|
||||
if (rta->rta_type != IFLA_STATS) continue;
|
||||
stats_len = RTA_DATALEN(rta);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
for (ifs0 = ctx->hash[ifa->ifa_index % IFADDRS_HASH_SIZE]; ifs0; ifs0 = ifs0->hash_next)
|
||||
if (ifs0->index == ifa->ifa_index)
|
||||
break;
|
||||
if (!ifs0) return 0;
|
||||
}
|
||||
|
||||
ifs = calloc(1, sizeof(struct ifaddrs_storage) + stats_len);
|
||||
if (ifs == 0) return -1;
|
||||
|
||||
if (h->nlmsg_type == RTM_NEWLINK) {
|
||||
ifs->index = ifi->ifi_index;
|
||||
ifs->ifa.ifa_flags = ifi->ifi_flags;
|
||||
|
||||
for (rta = NLMSG_RTA(h, sizeof(*ifi)); NLMSG_RTAOK(rta, h); rta = RTA_NEXT(rta)) {
|
||||
switch (rta->rta_type) {
|
||||
case IFLA_IFNAME:
|
||||
if (RTA_DATALEN(rta) < sizeof(ifs->name)) {
|
||||
memcpy(ifs->name, RTA_DATA(rta), RTA_DATALEN(rta));
|
||||
ifs->ifa.ifa_name = ifs->name;
|
||||
}
|
||||
break;
|
||||
case IFLA_ADDRESS:
|
||||
copy_lladdr(&ifs->ifa.ifa_addr, &ifs->addr, RTA_DATA(rta), RTA_DATALEN(rta), ifi->ifi_index, ifi->ifi_type);
|
||||
break;
|
||||
case IFLA_BROADCAST:
|
||||
copy_lladdr(&ifs->ifa.ifa_broadaddr, &ifs->ifu, RTA_DATA(rta), RTA_DATALEN(rta), ifi->ifi_index, ifi->ifi_type);
|
||||
break;
|
||||
case IFLA_STATS:
|
||||
ifs->ifa.ifa_data = (void*)(ifs+1);
|
||||
memcpy(ifs->ifa.ifa_data, RTA_DATA(rta), RTA_DATALEN(rta));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ifs->ifa.ifa_name) {
|
||||
unsigned int bucket = ifs->index % IFADDRS_HASH_SIZE;
|
||||
ifs->hash_next = ctx->hash[bucket];
|
||||
ctx->hash[bucket] = ifs;
|
||||
}
|
||||
} else {
|
||||
ifs->ifa.ifa_name = ifs0->ifa.ifa_name;
|
||||
ifs->ifa.ifa_flags = ifs0->ifa.ifa_flags;
|
||||
for (rta = NLMSG_RTA(h, sizeof(*ifa)); NLMSG_RTAOK(rta, h); rta = RTA_NEXT(rta)) {
|
||||
switch (rta->rta_type) {
|
||||
case IFA_ADDRESS:
|
||||
/* If ifa_addr is already set we, received an IFA_LOCAL before
|
||||
* so treat this as destination address */
|
||||
if (ifs->ifa.ifa_addr)
|
||||
copy_addr(&ifs->ifa.ifa_dstaddr, ifa->ifa_family, &ifs->ifu, RTA_DATA(rta), RTA_DATALEN(rta), ifa->ifa_index);
|
||||
else
|
||||
copy_addr(&ifs->ifa.ifa_addr, ifa->ifa_family, &ifs->addr, RTA_DATA(rta), RTA_DATALEN(rta), ifa->ifa_index);
|
||||
break;
|
||||
case IFA_BROADCAST:
|
||||
copy_addr(&ifs->ifa.ifa_broadaddr, ifa->ifa_family, &ifs->ifu, RTA_DATA(rta), RTA_DATALEN(rta), ifa->ifa_index);
|
||||
break;
|
||||
case IFA_LOCAL:
|
||||
/* If ifa_addr is set and we get IFA_LOCAL, assume we have
|
||||
* a point-to-point network. Move address to correct field. */
|
||||
if (ifs->ifa.ifa_addr) {
|
||||
ifs->ifu = ifs->addr;
|
||||
ifs->ifa.ifa_dstaddr = &ifs->ifu.sa;
|
||||
memset(&ifs->addr, 0, sizeof(ifs->addr));
|
||||
}
|
||||
copy_addr(&ifs->ifa.ifa_addr, ifa->ifa_family, &ifs->addr, RTA_DATA(rta), RTA_DATALEN(rta), ifa->ifa_index);
|
||||
break;
|
||||
case IFA_LABEL:
|
||||
if (RTA_DATALEN(rta) < sizeof(ifs->name)) {
|
||||
memcpy(ifs->name, RTA_DATA(rta), RTA_DATALEN(rta));
|
||||
ifs->ifa.ifa_name = ifs->name;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ifs->ifa.ifa_addr)
|
||||
gen_netmask(&ifs->ifa.ifa_netmask, ifa->ifa_family, &ifs->netmask, ifa->ifa_prefixlen);
|
||||
}
|
||||
|
||||
if (ifs->ifa.ifa_name) {
|
||||
if (!ctx->first) ctx->first = &ifs->ifa;
|
||||
if (ctx->last) ctx->last->ifa_next = &ifs->ifa;
|
||||
ctx->last = &ifs->ifa;
|
||||
} else {
|
||||
free(ifs);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getifaddrs(struct ifaddrs **ifap)
|
||||
{
|
||||
struct ifaddrs_ctx _ctx, *ctx = &_ctx;
|
||||
int r;
|
||||
memset(ctx, 0, sizeof *ctx);
|
||||
r = __rtnetlink_enumerate(AF_UNSPEC, AF_UNSPEC, netlink_msg_to_ifaddr, ctx);
|
||||
if (r == 0) *ifap = ctx->first;
|
||||
else freeifaddrs(ctx->first);
|
||||
return r;
|
||||
}
|
||||
8
nfq2/andr/ifaddrs.h
Normal file
8
nfq2/andr/ifaddrs.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <ifaddrs.h>
|
||||
|
||||
#if __ANDROID_API__ < 24
|
||||
void freeifaddrs(struct ifaddrs *);
|
||||
int getifaddrs(struct ifaddrs **);
|
||||
#endif
|
||||
54
nfq2/andr/netlink.c
Normal file
54
nfq2/andr/netlink.c
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <syscall.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "netlink.h"
|
||||
|
||||
static int __netlink_enumerate(int fd, unsigned int seq, int type, int af,
|
||||
int (*cb)(void *ctx, struct nlmsghdr *h), void *ctx)
|
||||
{
|
||||
struct nlmsghdr *h;
|
||||
union {
|
||||
uint8_t buf[8192];
|
||||
struct {
|
||||
struct nlmsghdr nlh;
|
||||
struct rtgenmsg g;
|
||||
} req;
|
||||
struct nlmsghdr reply;
|
||||
} u;
|
||||
int r, ret;
|
||||
|
||||
memset(&u.req, 0, sizeof(u.req));
|
||||
u.req.nlh.nlmsg_len = sizeof(u.req);
|
||||
u.req.nlh.nlmsg_type = type;
|
||||
u.req.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
|
||||
u.req.nlh.nlmsg_seq = seq;
|
||||
u.req.g.rtgen_family = af;
|
||||
r = send(fd, &u.req, sizeof(u.req), 0);
|
||||
if (r < 0) return r;
|
||||
|
||||
while (1) {
|
||||
r = recv(fd, u.buf, sizeof(u.buf), 0);
|
||||
if (r <= 0) return -1;
|
||||
for (h = &u.reply; NLMSG_OK(h, (void*)&u.buf[r]); h = NLMSG_NEXT(h)) {
|
||||
if (h->nlmsg_type == NLMSG_DONE) return 0;
|
||||
if (h->nlmsg_type == NLMSG_ERROR) return -1;
|
||||
ret = cb(ctx, h);
|
||||
if (ret) return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int __rtnetlink_enumerate(int link_af, int addr_af, int (*cb)(void *ctx, struct nlmsghdr *h), void *ctx)
|
||||
{
|
||||
int fd, r;
|
||||
|
||||
fd = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_ROUTE);
|
||||
if (fd < 0) return -1;
|
||||
r = __netlink_enumerate(fd, 1, RTM_GETLINK, link_af, cb, ctx);
|
||||
if (!r) r = __netlink_enumerate(fd, 2, RTM_GETADDR, addr_af, cb, ctx);
|
||||
close(fd);
|
||||
return r;
|
||||
}
|
||||
94
nfq2/andr/netlink.h
Normal file
94
nfq2/andr/netlink.h
Normal file
@@ -0,0 +1,94 @@
|
||||
#include <stdint.h>
|
||||
|
||||
/* linux/netlink.h */
|
||||
|
||||
#define NETLINK_ROUTE 0
|
||||
|
||||
struct nlmsghdr {
|
||||
uint32_t nlmsg_len;
|
||||
uint16_t nlmsg_type;
|
||||
uint16_t nlmsg_flags;
|
||||
uint32_t nlmsg_seq;
|
||||
uint32_t nlmsg_pid;
|
||||
};
|
||||
|
||||
#define NLM_F_REQUEST 1
|
||||
#define NLM_F_MULTI 2
|
||||
#define NLM_F_ACK 4
|
||||
|
||||
#define NLM_F_ROOT 0x100
|
||||
#define NLM_F_MATCH 0x200
|
||||
#define NLM_F_ATOMIC 0x400
|
||||
#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH)
|
||||
|
||||
#define NLMSG_NOOP 0x1
|
||||
#define NLMSG_ERROR 0x2
|
||||
#define NLMSG_DONE 0x3
|
||||
#define NLMSG_OVERRUN 0x4
|
||||
|
||||
/* linux/rtnetlink.h */
|
||||
|
||||
#define RTM_NEWLINK 16
|
||||
#define RTM_GETLINK 18
|
||||
#define RTM_NEWADDR 20
|
||||
#define RTM_GETADDR 22
|
||||
|
||||
struct rtattr {
|
||||
unsigned short rta_len;
|
||||
unsigned short rta_type;
|
||||
};
|
||||
|
||||
struct rtgenmsg {
|
||||
unsigned char rtgen_family;
|
||||
};
|
||||
|
||||
struct ifinfomsg {
|
||||
unsigned char ifi_family;
|
||||
unsigned char __ifi_pad;
|
||||
unsigned short ifi_type;
|
||||
int ifi_index;
|
||||
unsigned ifi_flags;
|
||||
unsigned ifi_change;
|
||||
};
|
||||
|
||||
/* linux/if_link.h */
|
||||
|
||||
#define IFLA_ADDRESS 1
|
||||
#define IFLA_BROADCAST 2
|
||||
#define IFLA_IFNAME 3
|
||||
#define IFLA_STATS 7
|
||||
|
||||
/* linux/if_addr.h */
|
||||
|
||||
struct ifaddrmsg {
|
||||
uint8_t ifa_family;
|
||||
uint8_t ifa_prefixlen;
|
||||
uint8_t ifa_flags;
|
||||
uint8_t ifa_scope;
|
||||
uint32_t ifa_index;
|
||||
};
|
||||
|
||||
#define IFA_ADDRESS 1
|
||||
#define IFA_LOCAL 2
|
||||
#define IFA_LABEL 3
|
||||
#define IFA_BROADCAST 4
|
||||
|
||||
/* musl */
|
||||
|
||||
#define NETLINK_ALIGN(len) (((len)+3) & ~3)
|
||||
#define NLMSG_DATA(nlh) ((void*)((char*)(nlh)+sizeof(struct nlmsghdr)))
|
||||
#define NLMSG_DATALEN(nlh) ((nlh)->nlmsg_len-sizeof(struct nlmsghdr))
|
||||
#define NLMSG_DATAEND(nlh) ((char*)(nlh)+(nlh)->nlmsg_len)
|
||||
#define NLMSG_NEXT(nlh) (struct nlmsghdr*)((char*)(nlh)+NETLINK_ALIGN((nlh)->nlmsg_len))
|
||||
#define NLMSG_OK(nlh,end) ((char*)(end)-(char*)(nlh) >= sizeof(struct nlmsghdr))
|
||||
|
||||
#define RTA_DATA(rta) ((void*)((char*)(rta)+sizeof(struct rtattr)))
|
||||
#define RTA_DATALEN(rta) ((rta)->rta_len-sizeof(struct rtattr))
|
||||
#define RTA_DATAEND(rta) ((char*)(rta)+(rta)->rta_len)
|
||||
#define RTA_NEXT(rta) (struct rtattr*)((char*)(rta)+NETLINK_ALIGN((rta)->rta_len))
|
||||
#define RTA_OK(rta,end) ((char*)(end)-(char*)(rta) >= sizeof(struct rtattr))
|
||||
|
||||
#define NLMSG_RTA(nlh,len) ((void*)((char*)(nlh)+sizeof(struct nlmsghdr)+NETLINK_ALIGN(len)))
|
||||
#define NLMSG_RTAOK(rta,nlh) RTA_OK(rta,NLMSG_DATAEND(nlh))
|
||||
|
||||
int __rtnetlink_enumerate(int link_af, int addr_af, int (*cb)(void *ctx, struct nlmsghdr *h), void *ctx);
|
||||
@@ -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,51 @@ 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);
|
||||
}
|
||||
#define csum_partial(buff, len) do_csum((const uint8_t*)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 ~csum_partial(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,20 +138,38 @@ 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);
|
||||
else if (ip6hdr)
|
||||
udp6_fix_checksum(udp, len, &ip6hdr->ip6_src, &ip6hdr->ip6_dst);
|
||||
}
|
||||
|
||||
void icmp4_fix_checksum(struct icmp46 *icmp, size_t len)
|
||||
{
|
||||
icmp->icmp_cksum = 0;
|
||||
icmp->icmp_cksum = ~csum_partial(icmp, len);
|
||||
}
|
||||
void icmp6_fix_checksum(struct icmp46 *icmp, size_t len, const struct ip6_hdr *ip6hdr)
|
||||
{
|
||||
icmp->icmp_cksum = 0;
|
||||
icmp->icmp_cksum = csum_ipv6_magic(&ip6hdr->ip6_src, &ip6hdr->ip6_dst, len, IPPROTO_ICMPV6, csum_partial(icmp, len));
|
||||
}
|
||||
void icmp_fix_checksum(struct icmp46 *icmp, size_t len, const struct ip6_hdr *ip6hdr)
|
||||
{
|
||||
if (ip6hdr)
|
||||
icmp6_fix_checksum(icmp, len, ip6hdr);
|
||||
else
|
||||
icmp4_fix_checksum(icmp, len);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,20 @@
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
uint16_t csum_partial(const void *buff, size_t len);
|
||||
// icmp 4 and 6 are basically compatible although checksums are calculated differently
|
||||
// do not use version specific structs
|
||||
struct icmp46
|
||||
{
|
||||
uint8_t icmp_type, icmp_code;
|
||||
uint16_t icmp_cksum;
|
||||
union
|
||||
{
|
||||
uint32_t data32;
|
||||
uint16_t data16[2];
|
||||
uint8_t data8[4];
|
||||
} data;
|
||||
};
|
||||
|
||||
uint16_t csum_tcpudp_magic(uint32_t saddr, uint32_t daddr, size_t len, uint8_t proto, uint16_t sum);
|
||||
uint16_t csum_ipv6_magic(const void *saddr, const void *daddr, size_t len, uint8_t proto, uint16_t sum);
|
||||
|
||||
@@ -25,3 +38,7 @@ void tcp_fix_checksum(struct tcphdr *tcp,size_t len,const struct ip *ip,const st
|
||||
void udp4_fix_checksum(struct udphdr *udp,size_t len, const struct in_addr *src_addr, const struct in_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);
|
||||
void udp_fix_checksum(struct udphdr *udp,size_t len,const struct ip *ip,const struct ip6_hdr *ip6hdr);
|
||||
|
||||
void icmp4_fix_checksum(struct icmp46 *icmp, size_t len);
|
||||
void icmp6_fix_checksum(struct icmp46 *icmp, size_t len, const struct ip6_hdr *ip6hdr);
|
||||
void icmp_fix_checksum(struct icmp46 *icmp, size_t len, const struct ip6_hdr *ip6hdr);
|
||||
|
||||
173
nfq2/conntrack.c
173
nfq2/conntrack.c
@@ -1,3 +1,4 @@
|
||||
#define _GNU_SOURCE
|
||||
#include "conntrack.h"
|
||||
#include "darkmagic.h"
|
||||
#include <arpa/inet.h>
|
||||
@@ -66,28 +67,29 @@ void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_s
|
||||
p->timeout_fin = timeout_fin;
|
||||
p->timeout_udp = timeout_udp;
|
||||
p->t_purge_interval = purge_interval;
|
||||
time(&p->t_last_purge);
|
||||
p->t_last_purge = boottime();
|
||||
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)
|
||||
bool 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);
|
||||
return false;
|
||||
extract_ports(dis->tcp, dis->udp, &c->l4proto, bReverse ? &c->dport : &c->sport, bReverse ? &c->sport : &c->dport);
|
||||
return c->l4proto!=IPPROTO_NONE;
|
||||
}
|
||||
|
||||
|
||||
@@ -102,7 +104,7 @@ static void ConntrackInitTrack(t_ctrack *t)
|
||||
{
|
||||
memset(t, 0, sizeof(*t));
|
||||
t->l7proto = L7_UNKNOWN;
|
||||
t->pos.client.scale = t->pos.server.scale = SCALE_NONE;
|
||||
t->pos.client.scale = t->pos.server.scale = 0;
|
||||
rawpacket_queue_init(&t->delayed);
|
||||
lua_newtable(params.L);
|
||||
t->lua_state = luaL_ref(params.L, LUA_REGISTRYINDEX);
|
||||
@@ -127,7 +129,7 @@ static t_conntrack_pool *ConntrackNew(t_conntrack_pool **pp, const t_conn *c)
|
||||
return ctnew;
|
||||
}
|
||||
|
||||
static void ConntrackApplyPos(const struct tcphdr *tcp, t_ctrack *t, bool bReverse, uint32_t len_payload)
|
||||
static void ConntrackApplyPos(t_ctrack *t, bool bReverse, const struct dissect *dis)
|
||||
{
|
||||
uint8_t scale;
|
||||
uint16_t mss;
|
||||
@@ -136,64 +138,71 @@ static void ConntrackApplyPos(const struct tcphdr *tcp, t_ctrack *t, bool bRever
|
||||
direct = bReverse ? &t->pos.server : &t->pos.client;
|
||||
reverse = bReverse ? &t->pos.client : &t->pos.server;
|
||||
|
||||
scale = tcp_find_scale_factor(tcp);
|
||||
mss = ntohs(tcp_find_mss(tcp));
|
||||
if (dis->ip6) direct->ip6flow = ntohl(dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_flow);
|
||||
|
||||
direct->seq_last = ntohl(tcp->th_seq);
|
||||
direct->pos = direct->seq_last + len_payload;
|
||||
reverse->pos = reverse->seq_last = ntohl(tcp->th_ack);
|
||||
direct->winsize_calc = direct->winsize = ntohs(dis->tcp->th_win);
|
||||
if (t->pos.state == SYN)
|
||||
{
|
||||
// scale and mss only valid in syn packets
|
||||
scale = tcp_find_scale_factor(dis->tcp);
|
||||
if (scale != SCALE_NONE) direct->scale = scale;
|
||||
direct->mss = tcp_find_mss(dis->tcp);
|
||||
}
|
||||
else
|
||||
// apply scale only outside of the SYN stage
|
||||
direct->winsize_calc <<= direct->scale;
|
||||
|
||||
direct->seq_last = ntohl(dis->tcp->th_seq);
|
||||
direct->pos = direct->seq_last + dis->len_payload;
|
||||
reverse->pos = reverse->seq_last = ntohl(dis->tcp->th_ack);
|
||||
if (t->pos.state == SYN)
|
||||
direct->uppos_prev = direct->uppos = direct->pos;
|
||||
else if (len_payload)
|
||||
else if (dis->len_payload)
|
||||
{
|
||||
direct->uppos_prev = direct->uppos;
|
||||
if (!((direct->pos - direct->uppos) & 0x80000000))
|
||||
direct->uppos = direct->pos;
|
||||
}
|
||||
direct->winsize = ntohs(tcp->th_win);
|
||||
direct->winsize_calc = direct->winsize;
|
||||
if (direct->scale != SCALE_NONE) direct->winsize_calc <<= direct->scale;
|
||||
if (mss && !direct->mss) direct->mss = mss;
|
||||
if (scale != SCALE_NONE) direct->scale = scale;
|
||||
|
||||
if (!direct->rseq_over_2G && ((direct->seq_last - direct->seq0) & 0x80000000))
|
||||
direct->rseq_over_2G = true;
|
||||
if (!reverse->rseq_over_2G && ((reverse->seq_last - reverse->seq0) & 0x80000000))
|
||||
reverse->rseq_over_2G = true;
|
||||
}
|
||||
|
||||
// non-tcp packets are passed with tcphdr=NULL but len_payload filled
|
||||
static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr *tcphdr, uint32_t len_payload)
|
||||
static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct dissect *dis)
|
||||
{
|
||||
uint8_t scale;
|
||||
uint16_t mss;
|
||||
|
||||
if (bReverse)
|
||||
{
|
||||
t->pos.server.pcounter++;
|
||||
t->pos.server.pdcounter += !!len_payload;
|
||||
t->pos.server.pbcounter += len_payload;
|
||||
t->pos.server.pdcounter += !!dis->len_payload;
|
||||
t->pos.server.pbcounter += dis->len_payload;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
t->pos.client.pcounter++;
|
||||
t->pos.client.pdcounter += !!len_payload;
|
||||
t->pos.client.pbcounter += len_payload;
|
||||
t->pos.client.pdcounter += !!dis->len_payload;
|
||||
t->pos.client.pbcounter += dis->len_payload;
|
||||
}
|
||||
|
||||
if (tcphdr)
|
||||
if (dis->tcp)
|
||||
{
|
||||
if (tcp_syn_segment(tcphdr))
|
||||
if (tcp_syn_segment(dis->tcp))
|
||||
{
|
||||
if (t->pos.state != SYN) ConntrackReInitTrack(t); // erase current entry
|
||||
t->pos.client.seq0 = ntohl(tcphdr->th_seq);
|
||||
t->pos.client.seq0 = ntohl(dis->tcp->th_seq);
|
||||
}
|
||||
else if (tcp_synack_segment(tcphdr))
|
||||
else if (tcp_synack_segment(dis->tcp))
|
||||
{
|
||||
// ignore SA dups
|
||||
uint32_t seq0 = ntohl(tcphdr->th_ack) - 1;
|
||||
uint32_t seq0 = ntohl(dis->tcp->th_ack) - 1;
|
||||
if (t->pos.state != SYN && t->pos.client.seq0 != seq0)
|
||||
ConntrackReInitTrack(t); // erase current entry
|
||||
if (!t->pos.client.seq0) t->pos.client.seq0 = seq0;
|
||||
t->pos.server.seq0 = ntohl(tcphdr->th_seq);
|
||||
t->pos.server.seq0 = ntohl(dis->tcp->th_seq);
|
||||
}
|
||||
else if (tcphdr->th_flags & (TH_FIN | TH_RST))
|
||||
else if (dis->tcp->th_flags & (TH_FIN | TH_RST))
|
||||
{
|
||||
t->pos.state = FIN;
|
||||
}
|
||||
@@ -202,36 +211,24 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
||||
if (t->pos.state == SYN)
|
||||
{
|
||||
t->pos.state = ESTABLISHED;
|
||||
if (!bReverse && !t->pos.server.seq0) t->pos.server.seq0 = ntohl(tcphdr->th_ack) - 1;
|
||||
if (!bReverse && !t->pos.server.seq0) t->pos.server.seq0 = ntohl(dis->tcp->th_ack) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
ConntrackApplyPos(tcphdr, t, bReverse, len_payload);
|
||||
ConntrackApplyPos(t, bReverse, dis);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bReverse)
|
||||
{
|
||||
t->pos.server.seq_last = t->pos.server.pos;
|
||||
t->pos.server.pos += len_payload;
|
||||
}
|
||||
else
|
||||
{
|
||||
t->pos.client.seq_last = t->pos.client.pos;
|
||||
t->pos.client.pos += len_payload;
|
||||
}
|
||||
}
|
||||
clock_gettime(CLOCK_REALTIME, &t->pos.t_last);
|
||||
|
||||
clock_gettime(CLOCK_BOOT_OR_UPTIME, &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);
|
||||
if (!ConntrackExtractConn(&conn, false, dis)) return false;
|
||||
if ((ctr = ConntrackPoolSearch(*pp, &conn)))
|
||||
{
|
||||
if (bReverse) *bReverse = false;
|
||||
@@ -250,22 +247,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);
|
||||
if (!ConntrackExtractConn(&conn, false, dis)) return false;
|
||||
if ((ctr = ConntrackPoolSearch(*pp, &conn)))
|
||||
{
|
||||
ConntrackFeedPacket(&ctr->track, (b_rev = false), tcphdr, len_payload);
|
||||
ConntrackFeedPacket(&ctr->track, (b_rev = false), dis);
|
||||
goto ok;
|
||||
}
|
||||
else
|
||||
@@ -273,36 +270,36 @@ 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;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
ok:
|
||||
ctr->track.ipproto = proto;
|
||||
ctr->track.pos.ipproto = proto;
|
||||
if (ctrack) *ctrack = &ctr->track;
|
||||
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);
|
||||
if (!ConntrackExtractConn(&conn, false, dis)) return false;
|
||||
if (!(t = ConntrackPoolSearch(*pp, &conn)))
|
||||
{
|
||||
connswap(&conn, &connswp);
|
||||
@@ -312,22 +309,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;
|
||||
struct timespec tnow;
|
||||
time_t tnow;
|
||||
t_conntrack_pool *t, *tmp;
|
||||
|
||||
if (clock_gettime(CLOCK_REALTIME, &tnow)) return;
|
||||
if ((tnow.tv_sec - p->t_last_purge) >= p->t_purge_interval)
|
||||
if (!(tnow=boottime())) return;
|
||||
if ((tnow - p->t_last_purge) >= p->t_purge_interval)
|
||||
{
|
||||
HASH_ITER(hh, p->pool, t, tmp) {
|
||||
tidle = tnow.tv_sec - t->track.pos.t_last.tv_sec;
|
||||
tidle = tnow - 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) ||
|
||||
@@ -339,7 +336,7 @@ void ConntrackPoolPurge(t_conntrack *p)
|
||||
HASH_DEL(p->pool, t); ConntrackFreeElem(t);
|
||||
}
|
||||
}
|
||||
p->t_last_purge = tnow.tv_sec;
|
||||
p->t_last_purge = tnow;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,18 +348,18 @@ 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;
|
||||
char sa1[INET6_ADDRSTRLEN], sa2[INET6_ADDRSTRLEN];
|
||||
|
||||
if (clock_gettime(CLOCK_REALTIME, &tnow)) return;
|
||||
if (!(tnow=boottime())) 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 client=d%llu/n%llu/b%llu server=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%llu ",
|
||||
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.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.t_start.tv_sec, (unsigned long long)(t->track.pos.t_last.tv_sec - t->track.t_start.tv_sec), (unsigned long long)(tnow - 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)
|
||||
@@ -370,14 +367,14 @@ void ConntrackPoolDump(const t_conntrack *p)
|
||||
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);
|
||||
t->track.pos.client.winsize, t->track.pos.client.scale,
|
||||
t->track.pos.server.winsize, t->track.pos.server.scale);
|
||||
else
|
||||
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));
|
||||
t->track.req_retrans_counter, t->track.b_cutoff, t->track.b_lua_in_cutoff, t->track.b_lua_out_cutoff, t->track.hostname ? t->track.hostname : "", l7proto_str(t->track.l7proto));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -424,7 +421,7 @@ bool ReasmFeed(t_reassemble *reasm, uint32_t seq, const void *payload, size_t le
|
||||
if ((reasm->size_present - neg_overlap + szcopy) > reasm->size)
|
||||
return false; // buffer overflow
|
||||
// in case of seq overlap new data replaces old - unix behavior
|
||||
memcpy(reasm->packet + reasm->size_present - neg_overlap, payload + szignore, szcopy);
|
||||
memcpy(reasm->packet + reasm->size_present - neg_overlap, (const uint8_t*)payload + szignore, szcopy);
|
||||
if (szcopy>neg_overlap)
|
||||
{
|
||||
reasm->size_present += szcopy - neg_overlap;
|
||||
|
||||
@@ -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
|
||||
@@ -52,7 +53,6 @@ typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
bool bCheckDone, bCheckResult, bCheckExcluded; // hostlist check result cache
|
||||
uint8_t ipproto;
|
||||
|
||||
struct timespec t_start;
|
||||
|
||||
@@ -100,11 +100,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);
|
||||
bool 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);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user