mirror of
https://github.com/bol-van/zapret2.git
synced 2026-03-16 06:52:30 +00:00
Compare commits
478 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
7708021587 | ||
|
|
912aadf6ca | ||
|
|
420cc0c3ef | ||
|
|
6ce5829d06 | ||
|
|
a6d43af931 | ||
|
|
ca9898959e | ||
|
|
8cd2904614 | ||
|
|
0de1ab1b1b | ||
|
|
d1690aadcf | ||
|
|
2dd8533fb5 | ||
|
|
33ac18ea6b | ||
|
|
5c05c10f83 | ||
|
|
7de0995d4a | ||
|
|
a1c64e4dea | ||
|
|
92b66b1535 | ||
|
|
9bf4fb11e7 | ||
|
|
7deeb04207 | ||
|
|
776155a326 | ||
|
|
30423596ca | ||
|
|
27ef67adf9 | ||
|
|
bb604f111c | ||
|
|
e5174bc9ad | ||
|
|
6c29bf6702 | ||
|
|
976033be37 | ||
|
|
f9b2135688 | ||
|
|
844fa6ab47 | ||
|
|
dc0fe70bd6 | ||
|
|
2752c26795 | ||
|
|
1600b41135 | ||
|
|
2017889207 | ||
|
|
146ab847df | ||
|
|
cf9059ed22 | ||
|
|
c94264c79e | ||
|
|
04cb71150a | ||
|
|
378ee514c4 | ||
|
|
1a190fcf9e | ||
|
|
0f8a788351 | ||
|
|
4c00f11c15 | ||
|
|
0f8cfd7022 | ||
|
|
4563b6ddcb | ||
|
|
9ae6927a0e | ||
|
|
8540278c9b | ||
|
|
76b9ab5075 | ||
|
|
3a153035e8 | ||
|
|
2b5eb3cd2d | ||
|
|
2c35e8949a | ||
|
|
7edd428508 | ||
|
|
7749fce7dc | ||
|
|
ea6e1e0853 | ||
|
|
7d2f12cbad | ||
|
|
f91c069a8b | ||
|
|
6961c013c5 | ||
|
|
e5736b5fdd | ||
|
|
efa675468d | ||
|
|
1073f03802 | ||
|
|
9125cb0205 | ||
|
|
9d5435f977 | ||
|
|
f17ab4c91e | ||
|
|
97aa261e14 | ||
|
|
813fece07a | ||
|
|
2a7b44b1d0 | ||
|
|
28e719d825 | ||
|
|
18725f6442 | ||
|
|
20b20fbb90 | ||
|
|
967b53b628 | ||
|
|
9cebc5cc37 | ||
|
|
0dc29c9c35 | ||
|
|
fd1eac2ef1 | ||
|
|
0c2abab6a9 | ||
|
|
efd8acb8de | ||
|
|
a147ebef61 | ||
|
|
7f4bdd5eb4 | ||
|
|
0588240d8d | ||
|
|
b9e03ef71b | ||
|
|
9c0c7cfa8c | ||
|
|
807ad5953b | ||
|
|
ee031db3a1 | ||
|
|
93e4df72e5 | ||
|
|
e62d3919f4 | ||
|
|
63414f8608 | ||
|
|
18974e6c1f | ||
|
|
e61967ac2b | ||
|
|
6010307667 | ||
|
|
04ceb589e0 | ||
|
|
69b08f0a36 | ||
|
|
ec6021898b | ||
|
|
711eefed3e | ||
|
|
032b24f5b4 | ||
|
|
ef4b427836 | ||
|
|
a795b0f10c | ||
|
|
b56be286c9 | ||
|
|
63668fc84e | ||
|
|
837833feaf | ||
|
|
90afc96283 | ||
|
|
b0455bfee2 | ||
|
|
d279fab308 | ||
|
|
27695a892f | ||
|
|
151226dfc2 | ||
|
|
ef78f8d30c | ||
|
|
a01408a5c9 | ||
|
|
50ae834005 | ||
|
|
b21e85bfe9 |
3
.github/workflows/build.yml
vendored
3
.github/workflows/build.yml
vendored
@@ -108,7 +108,7 @@ jobs:
|
||||
export PKG_CONFIG_PATH=$DEPS_DIR/lib/pkgconfig
|
||||
export STAGING_DIR=$RUNNER_TEMP
|
||||
|
||||
if [[ "$ARCH" == lexra ]] || [[ "$ARCH" == ppc ]]; then
|
||||
if [[ "$ARCH" == lexra ]] || [[ "$ARCH" == ppc ]] || [[ "$ARCH" == x86 ]] ; then
|
||||
# use classic lua
|
||||
wget -qO- https://www.lua.org/ftp/lua-${LUA_RELEASE}.tar.gz | tar -xz
|
||||
(
|
||||
@@ -553,6 +553,7 @@ jobs:
|
||||
rm -rf binaries/{android*,freebsd*,win*} \
|
||||
init.d/{openrc,pfsense,runit,s6,systemd,windivert.filter.examples} \
|
||||
nfq2 ip2net mdig docs Makefile
|
||||
gzip lua/*.lua
|
||||
)
|
||||
tar --owner=0 --group=0 -czf ${{ env.repo_dir }}-openwrt-embedded.tar.gz ${{ env.repo_dir }}
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@ pktws_simple_split_tests()
|
||||
# $3 - splits
|
||||
# $4 - PRE args for nfqws2
|
||||
local pos ok ok_any pre="$4"
|
||||
local splitf splitfs="multisplit multidisorder"
|
||||
local splitf splitfs="multisplit $MULTIDISORDER"
|
||||
|
||||
ok_any=0
|
||||
for splitf in multisplit multidisorder; do
|
||||
for splitf in $splitfs; do
|
||||
eval need_$splitf=0
|
||||
ok=0
|
||||
for pos in $3; do
|
||||
@@ -38,7 +38,7 @@ pktws_check_https_tls()
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
||||
local splits_tls='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,midsld,1220 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
||||
local PAYLOAD="--payload tls_client_hello"
|
||||
|
||||
[ "$NOTEST_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
@@ -24,8 +24,8 @@ pktws_check_http()
|
||||
for split in 'method+1 method+2' 'midsld-1 midsld' 'method+1 method+2,midsld'; do
|
||||
f="$(extract_arg 1 $split)"
|
||||
f2="$(extract_arg 2 $split)"
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=multidisorder:pos=$f2:seqovl=$f
|
||||
pktws_curl_test_update $1 $2 ${SEQOVL_PATTERN_HTTP:+--blob=$pat:@"$SEQOVL_PATTERN_HTTP" }$PAYLOAD --lua-desync=multidisorder:pos=$f2:seqovl=$f:seqovl_pattern=$pat
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f
|
||||
pktws_curl_test_update $1 $2 ${SEQOVL_PATTERN_HTTP:+--blob=$pat:@"$SEQOVL_PATTERN_HTTP" }$PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f:seqovl_pattern=$pat
|
||||
done
|
||||
}
|
||||
|
||||
@@ -60,8 +60,8 @@ pktws_seqovl_tests_tls()
|
||||
for split in '1 2' 'sniext sniext+1' 'sniext+3 sniext+4' 'midsld-1 midsld' '1 2,midsld'; do
|
||||
f="$(extract_arg 1 $split)"
|
||||
f2="$(extract_arg 2 $split)"
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=multidisorder:pos=$f2:seqovl=$f && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$rnd_mod $pre $PAYLOAD --lua-desync=multidisorder:pos=$f2:seqovl=$f:seqovl_pattern=$pat && ok=1
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f && ok=1
|
||||
pktws_curl_test_update $testf $domain ${SEQOVL_PATTERN_HTTPS:+--blob=$pat:@"$SEQOVL_PATTERN_HTTPS" }$rnd_mod $pre $PAYLOAD --lua-desync=$MULTIDISORDER:pos=$f2:seqovl=$f:seqovl_pattern=$pat && ok=1
|
||||
done
|
||||
[ "$ok" = 1 ] && ok_any=1
|
||||
[ "$ok_any" = 1 ]
|
||||
|
||||
49
blockcheck2.d/standard/24-syndata.sh
Normal file
49
blockcheck2.d/standard/24-syndata.sh
Normal file
@@ -0,0 +1,49 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
pktws_check_http()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
local PAYLOAD="--payload http_req" split
|
||||
|
||||
for split in '' multisplit $MULTIDISORDER; do
|
||||
pktws_curl_test_update "$1" "$2" --lua-desync=syndata ${split:+$PAYLOAD --lua-desync=$split}
|
||||
pktws_curl_test_update "$1" "$2" --lua-desync=syndata:blob=fake_default_http $PAYLOAD ${split:+$PAYLOAD --lua-desync=$split}
|
||||
done
|
||||
}
|
||||
|
||||
pktws_check_https_tls()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
|
||||
local PAYLOAD="--payload tls_client_hello" ok=0 pre="$3" split
|
||||
|
||||
for split in '' multisplit $MULTIDISORDER; do
|
||||
pktws_curl_test_update "$1" "$2" $pre --lua-desync=syndata ${split:+$PAYLOAD --lua-desync=$split} && ok=1
|
||||
pktws_curl_test_update "$1" "$2" $pre --lua-desync=syndata:blob=0x1603 ${split:+$PAYLOAD --lua-desync=$split} && ok=1
|
||||
pktws_curl_test_update "$1" "$2" $pre --lua-desync=syndata:blob=fake_default_tls:tls_mod=rnd,dupsid,rndsni ${split:+$PAYLOAD --lua-desync=$split} && ok=1
|
||||
pktws_curl_test_update "$1" "$2" $pre --lua-desync=syndata:blob=fake_default_tls:tls_mod=rnd,dupsid,sni=google.com ${split:+$PAYLOAD --lua-desync=$split} && ok=1
|
||||
done
|
||||
|
||||
[ "$ok" = 1 ]
|
||||
}
|
||||
|
||||
pktws_check_https_tls12()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
pktws_check_https_tls "$1" "$2" && [ "$SCANLEVEL" != force ] && return
|
||||
pktws_check_https_tls "$1" "$2" --lua-desync=wssize:wsize=1:scale=6
|
||||
}
|
||||
|
||||
pktws_check_https_tls13()
|
||||
{
|
||||
# $1 - test function
|
||||
# $2 - domain
|
||||
|
||||
pktws_check_https_tls "$1" "$2"
|
||||
}
|
||||
@@ -22,7 +22,7 @@ pktws_check_http()
|
||||
# do not test fake + multisplit if multisplit works
|
||||
[ "$need_multisplit" = 0 -a "$SCANLEVEL" != force ] || splitfs=multisplit
|
||||
# do not test fake + multidisorder if multidisorder works
|
||||
[ "$need_multidisorder" = 0 -a "$SCANLEVEL" != force ] || splitfs="${splitfs:+$splitfs }multidisorder"
|
||||
[ "$need_multidisorder" = 0 -a "$SCANLEVEL" != force ] || splitfs="${splitfs:+$splitfs }$MULTIDISORDER"
|
||||
|
||||
for splitf in $splitfs; do
|
||||
ok=0
|
||||
@@ -71,7 +71,7 @@ pktws_fake_https_vary_()
|
||||
shift; shift; shift
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain $pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=multisplit:blob=$fake:$fooling:pos=2:nodrop:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid,padencap:repeats=$FAKE_REPEATS --lua-desync=$splitf:pos=$split $post && ok_any=1
|
||||
[ "$ok_any" = 1 ] && ok=1
|
||||
@@ -95,7 +95,7 @@ pktws_check_https_tls()
|
||||
[ "$NOTEST_FAKE_MULTI_HTTPS" = 1 ] && { echo "SKIPPED"; return 0; }
|
||||
|
||||
local testf=$1 domain="$2" pre="$3"
|
||||
local ok ok_any ttls attls f fake fooling splitf splitfs= split splits='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
||||
local ok ok_any ttls attls f fake fooling splitf splitfs= split splits='2 1 sniext+1 sniext+4 host+1 midsld 1,midsld 1,midsld,1220 1,sniext+1,host+1,midsld-2,midsld,midsld+2,endhost-1'
|
||||
local PAYLOAD="--payload=tls_client_hello"
|
||||
|
||||
shift; shift
|
||||
@@ -112,7 +112,7 @@ pktws_check_https_tls()
|
||||
# do not test fake + multisplit if multisplit works
|
||||
[ "$need_multisplit" = 0 -a "$SCANLEVEL" != force ] || splitfs=multisplit
|
||||
# do not test fake + multidisorder if multidisorder works
|
||||
[ "$need_multidisorder" = 0 -a "$SCANLEVEL" != force ] || splitfs="${splitfs:+$splitfs }multidisorder"
|
||||
[ "$need_multidisorder" = 0 -a "$SCANLEVEL" != force ] || splitfs="${splitfs:+$splitfs }$MULTIDISORDER"
|
||||
|
||||
ok_any=0
|
||||
for splitf in $splitfs; do
|
||||
|
||||
@@ -71,7 +71,7 @@ pktws_fake_https_vary_()
|
||||
shift; shift; shift
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=0x00000000:$fooling:repeats=$FAKE_REPEATS --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=multisplit:blob=$fake:$fooling:pos=2:nodrop:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
pktws_curl_test_update $testf $domain ${FAKE_HTTPS:+--blob=$fake:@"$FAKE_HTTPS" }${FAKED_PATTERN_HTTPS:+--blob=faked_pat:@"$FAKED_PATTERN_HTTPS" }$pre $PAYLOAD --lua-desync=fake:blob=$fake:$fooling:tls_mod=rnd,dupsid,padencap:repeats=$FAKE_REPEATS --lua-desync=$splitf:${FAKED_PATTERN_HTTPS+pattern=faked_pat:}pos=$split:$fooling $post && ok_any=1
|
||||
[ "$ok_any" = 1 ] && ok=1
|
||||
|
||||
@@ -29,7 +29,7 @@ pktws_check_hostfake()
|
||||
# $2 - domain
|
||||
# $3 - PRE args for nfqws2
|
||||
local testf=$1 domain="$2" pre="$3"
|
||||
local ok ttls attls f fake fooling
|
||||
local ok ttls attls f fooling
|
||||
|
||||
[ "$need_hostfakesplit" = 0 ] && return 0
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
. "$TESTDIR/def.inc"
|
||||
|
||||
pktws_check_http3()
|
||||
{
|
||||
# $1 - test function
|
||||
@@ -5,7 +7,7 @@ pktws_check_http3()
|
||||
|
||||
[ "$NOTEST_QUIC" = 1 ] && { echo "SKIPPED"; return; }
|
||||
|
||||
local repeats fake pos
|
||||
local repeats fake pos fool
|
||||
local PAYLOAD="--payload quic_initial"
|
||||
|
||||
if [ -n "$FAKE_QUIC" ]; then
|
||||
@@ -18,6 +20,12 @@ pktws_check_http3()
|
||||
pktws_curl_test_update $1 $2 ${FAKE_QUIC:+--blob=$fake:@"$FAKE_QUIC" }$PAYLOAD --lua-desync=fake:blob=$fake:repeats=$repeats && [ "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
|
||||
[ "$IPV" = 6 ] && {
|
||||
for fool in ip6_hopbyhop ip6_destopt ip6_hopbyhop:ip6_destopt; do
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=send:$fool --lua-desync=drop
|
||||
done
|
||||
}
|
||||
|
||||
for pos in 8 16 32 64; do
|
||||
pktws_curl_test_update $1 $2 $PAYLOAD --lua-desync=send:ipfrag:ipfrag_pos_udp=$pos --lua-desync=drop && [ "$SCANLEVEL" != force ] && break
|
||||
done
|
||||
|
||||
@@ -2,6 +2,16 @@ FOOLINGS46_TCP=${FOOLINGS46_TCP:-"tcp_md5 badsum tcp_seq=-3000 tcp_seq=1000000 t
|
||||
FOOLINGS6_TCP=${FOOLINGS6_TCP:-"ip6_hopbyhop ip6_hopbyhop:ip6_hopbyhop2 ip6_destopt ip6_routing ip6_ah"}
|
||||
FOOLINGS_TCP="$FOOLINGS46_TCP"
|
||||
[ "$IPV" = 6 ] && FOOLINGS_TCP="$FOOLINGS_TCP $FOOLINGS6_TCP"
|
||||
FOOLINGS_UDP="badsum"
|
||||
FOOLINGS6_UDP="${FOOLINGS6_UDP:-$FOOLINGS6_TCP}"
|
||||
FOOLINGS_UDP="${FOOLINGS_UDP:-badsum}"
|
||||
[ "$IPV" = 6 ] && FOOLINGS_UDP="$FOOLINGS_UDP $FOOLINGS6_UDP"
|
||||
|
||||
FAKE_REPEATS=${FAKE_REPEATS:-1}
|
||||
|
||||
MIN_TTL=${MIN_TTL:-1}
|
||||
MAX_TTL=${MAX_TTL:-12}
|
||||
MIN_AUTOTTL_DELTA=${MIN_AUTOTTL_DELTA:-1}
|
||||
MAX_AUTOTTL_DELTA=${MAX_AUTOTTL_DELTA:-5}
|
||||
|
||||
# can use MULTIDISORER=multidisorder_legacy
|
||||
MULTIDISORDER=${MULTIDISORDER:-multidisorder}
|
||||
|
||||
@@ -26,7 +26,7 @@ CURL=${CURL:-curl}
|
||||
|
||||
TEST_DEFAULT=${TEST_DEFAULT:-standard}
|
||||
DOMAINS_DEFAULT=${DOMAINS_DEFAULT:-rutracker.org}
|
||||
QNUM=${QNUM:-59780}
|
||||
QNUM=${QNUM:-59781}
|
||||
SOCKS_PORT=${SOCKS_PORT:-1993}
|
||||
WS_UID=${WS_UID:-1}
|
||||
WS_GID=${WS_GID:-3003}
|
||||
@@ -40,10 +40,6 @@ IPFW_DIVERT_PORT=${IPFW_DIVERT_PORT:-59780}
|
||||
CURL_MAX_TIME=${CURL_MAX_TIME:-2}
|
||||
CURL_MAX_TIME_QUIC=${CURL_MAX_TIME_QUIC:-$CURL_MAX_TIME}
|
||||
CURL_MAX_TIME_DOH=${CURL_MAX_TIME_DOH:-2}
|
||||
MIN_TTL=${MIN_TTL:-1}
|
||||
MAX_TTL=${MAX_TTL:-12}
|
||||
MIN_AUTOTTL_DELTA=${MIN_AUTOTTL_DELTA:-1}
|
||||
MAX_AUTOTTL_DELTA=${MAX_AUTOTTL_DELTA:-5}
|
||||
USER_AGENT=${USER_AGENT:-Mozilla}
|
||||
HTTP_PORT=${HTTP_PORT:-80}
|
||||
HTTPS_PORT=${HTTPS_PORT:-443}
|
||||
@@ -275,44 +271,45 @@ mdig_cache()
|
||||
mdig_resolve()
|
||||
{
|
||||
# $1 - ip version 4/6
|
||||
# $2 - hostname, possibly with uri : rutracker.org/xxx/xxxx
|
||||
local hostvar cachevar countvar count ip n sdom
|
||||
# $2 - var to receive result
|
||||
# $3 - hostname, possibly with uri : rutracker.org/xxx/xxxx
|
||||
local hostvar cachevar countvar count n sdom
|
||||
|
||||
split_by_separator "$2" / sdom
|
||||
split_by_separator "$3" / sdom
|
||||
mdig_vars "$1" "$sdom"
|
||||
if [ -n "$count" ]; then
|
||||
n=$(random 0 $(($count-1)))
|
||||
eval ip=\$${cachevar}_$n
|
||||
echo $ip
|
||||
eval $2=\$${cachevar}_$n
|
||||
return 0
|
||||
else
|
||||
mdig_cache "$1" "$sdom" && mdig_resolve "$1" "$sdom"
|
||||
mdig_cache "$1" "$sdom" && mdig_resolve "$1" "$2" "$sdom"
|
||||
fi
|
||||
}
|
||||
mdig_resolve_all()
|
||||
{
|
||||
# $1 - ip version 4/6
|
||||
# $2 - hostname
|
||||
# $2 - var to receive result
|
||||
# $3 - hostname
|
||||
|
||||
local hostvar cachevar countvar count ip ips n sdom
|
||||
local hostvar cachevar countvar count ip__ ips__ n sdom
|
||||
|
||||
split_by_separator "$2" / sdom
|
||||
split_by_separator "$3" / sdom
|
||||
mdig_vars "$1" "$sdom"
|
||||
if [ -n "$count" ]; then
|
||||
n=0
|
||||
while [ "$n" -le $count ]; do
|
||||
eval ip=\$${cachevar}_$n
|
||||
if [ -n "$ips" ]; then
|
||||
ips="$ips $ip"
|
||||
eval ip__=\$${cachevar}_$n
|
||||
if [ -n "$ips__" ]; then
|
||||
ips__="$ips__ $ip__"
|
||||
else
|
||||
ips="$ip"
|
||||
ips__="$ip__"
|
||||
fi
|
||||
n=$(($n + 1))
|
||||
done
|
||||
echo "$ips"
|
||||
eval $2="\$ips__"
|
||||
return 0
|
||||
else
|
||||
mdig_cache "$1" "$sdom" && mdig_resolve_all "$1" "$sdom"
|
||||
mdig_cache "$1" "$sdom" && mdig_resolve_all "$1" "$2" "$sdom"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -640,7 +637,7 @@ curl_with_dig()
|
||||
local sdom suri ip
|
||||
|
||||
split_by_separator "$dom" / sdom suri
|
||||
ip=$(mdig_resolve $1 $sdom)
|
||||
mdig_resolve $1 ip $sdom
|
||||
shift ; shift ; shift
|
||||
if [ -n "$ip" ]; then
|
||||
curl_with_subst_ip "$sdom" "$port" "$ip" "$@"
|
||||
@@ -965,7 +962,7 @@ check_domain_port_block()
|
||||
echo
|
||||
echo \* port block tests ipv$IPV $1:$2
|
||||
if netcat_setup; then
|
||||
ips=$(mdig_resolve_all $IPV $1)
|
||||
mdig_resolve_all $IPV ips $1
|
||||
if [ -n "$ips" ]; then
|
||||
for ip in $ips; do
|
||||
if netcat_test $ip $2; then
|
||||
@@ -1198,8 +1195,8 @@ test_runner()
|
||||
[ -f "$script" ] || continue
|
||||
unset -f $FUNC
|
||||
. "$script"
|
||||
echo
|
||||
existf $FUNC && {
|
||||
echo
|
||||
echo "* script : $TEST/$(basename "$script")"
|
||||
$FUNC "$@"
|
||||
}
|
||||
@@ -1254,7 +1251,7 @@ check_dpi_ip_block()
|
||||
|
||||
echo "> testing $UNBLOCKED_DOM on it's original ip"
|
||||
if curl_test $1 $UNBLOCKED_DOM; then
|
||||
unblocked_ip=$(mdig_resolve $IPV $UNBLOCKED_DOM)
|
||||
mdig_resolve $IPV unblocked_ip $UNBLOCKED_DOM
|
||||
[ -n "$unblocked_ip" ] || {
|
||||
echo $UNBLOCKED_DOM does not resolve. tests not possible.
|
||||
return 1
|
||||
@@ -1263,7 +1260,7 @@ check_dpi_ip_block()
|
||||
echo "> testing $blocked_dom on $unblocked_ip ($UNBLOCKED_DOM)"
|
||||
curl_test $1 $blocked_dom $unblocked_ip detail
|
||||
|
||||
blocked_ips=$(mdig_resolve_all $IPV $blocked_dom)
|
||||
mdig_resolve_all $IPV blocked_ips $blocked_dom
|
||||
for blocked_ip in $blocked_ips; do
|
||||
echo "> testing $UNBLOCKED_DOM on $blocked_ip ($blocked_dom)"
|
||||
curl_test $1 $UNBLOCKED_DOM $blocked_ip detail
|
||||
@@ -1314,6 +1311,8 @@ check_domain_http_tcp()
|
||||
# $3 - encrypted test : 0 = plain, 1 - encrypted with server reply risk, 2 - encrypted without server reply risk
|
||||
# $4 - domain
|
||||
|
||||
local ips
|
||||
|
||||
# in case was interrupted before
|
||||
pktws_ipt_unprepare_tcp $2
|
||||
ws_kill
|
||||
@@ -1325,7 +1324,8 @@ check_domain_http_tcp()
|
||||
[ "$SKIP_PKTWS" = 1 ] || {
|
||||
echo
|
||||
echo preparing $PKTWSD redirection
|
||||
pktws_ipt_prepare_tcp $2 "$(mdig_resolve_all $IPV $4)"
|
||||
mdig_resolve_all $IPV ips $4
|
||||
pktws_ipt_prepare_tcp $2 "$ips"
|
||||
|
||||
pktws_check_domain_http_bypass $1 $3 $4
|
||||
|
||||
@@ -1339,6 +1339,8 @@ check_domain_http_udp()
|
||||
# $2 - port
|
||||
# $3 - domain
|
||||
|
||||
local ips
|
||||
|
||||
# in case was interrupted before
|
||||
pktws_ipt_unprepare_udp $2
|
||||
ws_kill
|
||||
@@ -1348,7 +1350,8 @@ check_domain_http_udp()
|
||||
[ "$SKIP_PKTWS" = 1 ] || {
|
||||
echo
|
||||
echo preparing $PKTWSD redirection
|
||||
pktws_ipt_prepare_udp $2 "$(mdig_resolve_all $IPV $3)"
|
||||
mdig_resolve_all $IPV ips $3
|
||||
pktws_ipt_prepare_udp $2 "$ips"
|
||||
|
||||
pktws_check_domain_http3_bypass $1 $3
|
||||
|
||||
|
||||
@@ -4,6 +4,10 @@ which()
|
||||
# 'command -v' replacement does not work exactly the same way. it outputs shell aliases if present
|
||||
# $1 - executable name
|
||||
local IFS=:
|
||||
[ "$1" != "${1#/}" ] && [ -x "$1" ] && {
|
||||
echo "$1"
|
||||
return 0
|
||||
}
|
||||
for p in $PATH; do
|
||||
[ -x "$p/$1" ] && {
|
||||
echo "$p/$1"
|
||||
@@ -416,10 +420,10 @@ alloc_num()
|
||||
|
||||
std_ports()
|
||||
{
|
||||
NFQWS2_PORTS_TCP_IPT=$(replace_char - : $NFQWS_PORTS_TCP)
|
||||
NFQWS2_PORTS_TCP_KEEPALIVE_IPT=$(replace_char - : $NFQWS_PORTS_TCP_KEEPALIVE)
|
||||
NFQWS2_PORTS_UDP_IPT=$(replace_char - : $NFQWS_PORTS_UDP)
|
||||
NFQWS2_PORTS_UDP_KEEPALIVE_IPT=$(replace_char - : $NFQWS_PORTS_UDP_KEEPALIVE)
|
||||
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()
|
||||
|
||||
34
common/custom.sh
Normal file
34
common/custom.sh
Normal file
@@ -0,0 +1,34 @@
|
||||
custom_runner()
|
||||
{
|
||||
# $1 - function name
|
||||
# $2+ - params
|
||||
|
||||
[ "$DISABLE_CUSTOM" = 1 ] && return 0
|
||||
|
||||
local n script FUNC=$1
|
||||
|
||||
shift
|
||||
|
||||
[ -d "$CUSTOM_DIR/custom.d" ] && {
|
||||
dir_is_not_empty "$CUSTOM_DIR/custom.d" && {
|
||||
for script in "$CUSTOM_DIR/custom.d/"*; do
|
||||
[ -f "$script" ] || continue
|
||||
unset -f $FUNC
|
||||
. "$script"
|
||||
existf $FUNC && $FUNC "$@"
|
||||
done
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
alloc_qnum()
|
||||
{
|
||||
# $1 - target var name
|
||||
alloc_num NUMPOOL_QNUM $1 65300 65399
|
||||
}
|
||||
alloc_dnum()
|
||||
{
|
||||
# alloc daemon number
|
||||
# $1 - target var name
|
||||
alloc_num NUMPOOL_DNUM $1 2000 2999
|
||||
}
|
||||
803
common/installer.sh
Normal file
803
common/installer.sh
Normal file
@@ -0,0 +1,803 @@
|
||||
GET_LIST_PREFIX=/ipset/get_
|
||||
|
||||
SYSTEMD_DIR=/lib/systemd
|
||||
[ -d "$SYSTEMD_DIR" ] || SYSTEMD_DIR=/usr/lib/systemd
|
||||
[ -d "$SYSTEMD_DIR" ] && SYSTEMD_SYSTEM_DIR="$SYSTEMD_DIR/system"
|
||||
|
||||
INIT_SCRIPT=/etc/init.d/zapret2
|
||||
|
||||
|
||||
exitp()
|
||||
{
|
||||
echo
|
||||
echo press enter to continue
|
||||
read A
|
||||
exit $1
|
||||
}
|
||||
|
||||
extract_var_def()
|
||||
{
|
||||
# $1 - var name
|
||||
# this sed script parses single or multi line shell var assignments with optional ' or " enclosure
|
||||
sed -n \
|
||||
"/^$1=\"/ {
|
||||
:s1
|
||||
/\".*\"/ {
|
||||
p
|
||||
b
|
||||
}
|
||||
N
|
||||
t c1
|
||||
b s1
|
||||
:c1
|
||||
}
|
||||
/^$1='/ {
|
||||
:s2
|
||||
/'.*'/ {
|
||||
p
|
||||
b
|
||||
}
|
||||
N
|
||||
t c2
|
||||
b s2
|
||||
:c2
|
||||
}
|
||||
/^$1=/p
|
||||
"
|
||||
}
|
||||
replace_var_def()
|
||||
{
|
||||
# $1 - var name
|
||||
# $2 - new val
|
||||
# $3 - conf file
|
||||
# this sed script replaces single or multi line shell var assignments with optional ' or " enclosure
|
||||
local repl
|
||||
if [ -z "$2" ]; then
|
||||
repl="#$1="
|
||||
elif contains "$2" " "; then
|
||||
repl="$1=\"$2\""
|
||||
else
|
||||
repl="$1=$2"
|
||||
fi
|
||||
local script=\
|
||||
"/^#*[[:space:]]*$1=\"/ {
|
||||
:s1
|
||||
/\".*\"/ {
|
||||
c\\
|
||||
$repl
|
||||
b
|
||||
}
|
||||
N
|
||||
t c1
|
||||
b s1
|
||||
:c1
|
||||
}
|
||||
/^#*[[:space:]]*$1='/ {
|
||||
:s2
|
||||
/'.*'/ {
|
||||
c\\
|
||||
$repl
|
||||
b
|
||||
}
|
||||
N
|
||||
t c2
|
||||
b s2
|
||||
:c2
|
||||
}
|
||||
/^#*[[:space:]]*$1=/c\\
|
||||
$repl"
|
||||
# there's incompatibility with -i option on BSD and busybox/GNU
|
||||
if [ "$UNAME" = "Linux" ]; then
|
||||
sed -i -e "$script" "$3"
|
||||
else
|
||||
sed -i '' -e "$script" "$3"
|
||||
fi
|
||||
}
|
||||
|
||||
parse_var_checked()
|
||||
{
|
||||
# $1 - file name
|
||||
# $2 - var name
|
||||
|
||||
local tmp="/tmp/zvar-pid-$$.sh"
|
||||
local v
|
||||
cat "$1" | extract_var_def "$2" >"$tmp"
|
||||
. "$tmp"
|
||||
rm -f "$tmp"
|
||||
eval v="\$$2"
|
||||
# trim
|
||||
v="$(echo "$v" | trim)"
|
||||
eval $2=\""$v"\"
|
||||
}
|
||||
parse_vars_checked()
|
||||
{
|
||||
# $1 - file name
|
||||
# $2,$3,... - var names
|
||||
local f="$1"
|
||||
shift
|
||||
while [ -n "$1" ]; do
|
||||
parse_var_checked "$f" $1
|
||||
shift
|
||||
done
|
||||
}
|
||||
edit_file()
|
||||
{
|
||||
# $1 - file name
|
||||
local ed="$EDITOR"
|
||||
[ -n "$ed" ] || {
|
||||
for e in mcedit nano vim vi; do
|
||||
exists "$e" && {
|
||||
ed="$e"
|
||||
break
|
||||
}
|
||||
done
|
||||
}
|
||||
[ -n "$ed" ] && "$ed" "$1"
|
||||
}
|
||||
echo_var()
|
||||
{
|
||||
local v delimeter delims=
|
||||
eval v="\$$1"
|
||||
if find_str_in_list $1 "$EDITVAR_NEWLINE_VARS"; then
|
||||
echo "$1=\""
|
||||
for delimeter in $EDITVAR_NEWLINE_DELIMETERS; do
|
||||
delims="${delims:+$delims }-e "'"'"s/$delimeter/"'\\n'"$delimeter/g"'"'
|
||||
done
|
||||
echo "$v\"" | tr '\n' ' ' | tr -d '\r' | eval sed -e 's/^\ *//' -e 's/\ *$//' $delims
|
||||
else
|
||||
if contains "$v" " "; then
|
||||
echo $1=\"$v\"
|
||||
else
|
||||
echo $1=$v
|
||||
fi
|
||||
fi
|
||||
}
|
||||
edit_vars()
|
||||
{
|
||||
# $1,$2,... - var names
|
||||
local n=1 var tmp="/tmp/zvars-pid-$$.txt"
|
||||
rm -f "$tmp"
|
||||
while : ; do
|
||||
eval var="\${$n}"
|
||||
[ -n "$var" ] || break
|
||||
echo_var $var >> "$tmp"
|
||||
n=$(($n+1))
|
||||
done
|
||||
edit_file "$tmp" && parse_vars_checked "$tmp" "$@"
|
||||
rm -f "$tmp"
|
||||
}
|
||||
|
||||
list_vars()
|
||||
{
|
||||
while [ -n "$1" ] ; do
|
||||
echo_var $1
|
||||
shift
|
||||
done
|
||||
echo
|
||||
}
|
||||
|
||||
openrc_test()
|
||||
{
|
||||
exists rc-update || return 1
|
||||
# some systems do not usse openrc-init but launch openrc from inittab
|
||||
[ "$INIT" = "openrc-init" ] || grep -qE "sysinit.*openrc" /etc/inittab 2>/dev/null
|
||||
}
|
||||
check_system()
|
||||
{
|
||||
# $1 - nonempty = do not fail on unknown rc system
|
||||
|
||||
echo \* checking system
|
||||
|
||||
SYSTEM=
|
||||
SUBSYS=
|
||||
SYSTEMCTL="$(whichq systemctl)"
|
||||
|
||||
get_fwtype
|
||||
OPENWRT_FW3=
|
||||
OPENWRT_FW4=
|
||||
|
||||
local info
|
||||
UNAME=$(uname)
|
||||
if [ "$UNAME" = "Linux" ]; then
|
||||
# do not use 'exe' because it requires root
|
||||
local INIT="$(sed 's/\x0/\n/g' /proc/1/cmdline | head -n 1)"
|
||||
[ -L "$INIT" ] && INIT=$(readlink "$INIT")
|
||||
INIT="$(basename "$INIT")"
|
||||
# some distros include systemctl without systemd
|
||||
if [ -d "$SYSTEMD_DIR" ] && [ -x "$SYSTEMCTL" ] && [ "$INIT" = "systemd" ]; then
|
||||
SYSTEM=systemd
|
||||
[ -f "$EXEDIR/init.d/sysv/functions" ] && . "$EXEDIR/init.d/sysv/functions"
|
||||
elif [ -f "/etc/openwrt_release" ] && exists opkg || exists apk && exists uci && [ "$INIT" = "procd" ] ; then
|
||||
SYSTEM=openwrt
|
||||
OPENWRT_PACKAGER=opkg
|
||||
OPENWRT_PACKAGER_INSTALL="opkg install"
|
||||
OPENWRT_PACKAGER_UPDATE="opkg update"
|
||||
exists apk && {
|
||||
OPENWRT_PACKAGER=apk
|
||||
OPENWRT_PACKAGER_INSTALL="apk add"
|
||||
OPENWRT_PACKAGER_UPDATE=
|
||||
}
|
||||
info="package manager $OPENWRT_PACKAGER\n"
|
||||
if openwrt_fw3 ; then
|
||||
OPENWRT_FW3=1
|
||||
info="${info}firewall fw3"
|
||||
if is_ipt_flow_offload_avail; then
|
||||
info="$info. hardware flow offloading requires iptables."
|
||||
else
|
||||
info="$info. flow offloading unavailable."
|
||||
fi
|
||||
elif openwrt_fw4; then
|
||||
OPENWRT_FW4=1
|
||||
info="${info}firewall fw4. flow offloading requires nftables."
|
||||
fi
|
||||
[ -f "$EXEDIR/init.d/openwrt/functions" ] && . "$EXEDIR/init.d/openwrt/functions"
|
||||
elif openrc_test; then
|
||||
SYSTEM=openrc
|
||||
[ -f "$EXEDIR/init.d/sysv/functions" ] && . "$EXEDIR/init.d/sysv/functions"
|
||||
else
|
||||
echo system is not either systemd, openrc or openwrt based
|
||||
echo easy installer can set up config settings but can\'t configure auto start
|
||||
echo you have to do it manually. check readme.md for manual setup info.
|
||||
if [ -n "$1" ] || ask_yes_no N "do you want to continue"; then
|
||||
SYSTEM=linux
|
||||
else
|
||||
exitp 5
|
||||
fi
|
||||
[ -f "$EXEDIR/init.d/sysv/functions" ] && . "$EXEDIR/init.d/sysv/functions"
|
||||
fi
|
||||
linux_get_subsys
|
||||
else
|
||||
echo easy installer only supports Linux. check readme.md for supported systems and manual setup info.
|
||||
exitp 5
|
||||
fi
|
||||
echo system is based on $SYSTEM
|
||||
[ -n "$info" ] && printf "${info}\n"
|
||||
}
|
||||
|
||||
get_free_space_mb()
|
||||
{
|
||||
df -m $PWD | awk '/[0-9]%/{print $(NF-2)}'
|
||||
}
|
||||
get_ram_kb()
|
||||
{
|
||||
grep MemTotal /proc/meminfo | awk '{print $2}'
|
||||
}
|
||||
get_ram_mb()
|
||||
{
|
||||
local R=$(get_ram_kb)
|
||||
echo $(($R/1024))
|
||||
}
|
||||
|
||||
crontab_del()
|
||||
{
|
||||
exists crontab || return
|
||||
|
||||
echo \* removing crontab entry
|
||||
|
||||
CRONTMP=/tmp/cron.tmp
|
||||
crontab -l >$CRONTMP 2>/dev/null
|
||||
if grep -q "$GET_LIST_PREFIX" $CRONTMP; then
|
||||
echo removing following entries from crontab :
|
||||
grep "$GET_LIST_PREFIX" $CRONTMP
|
||||
grep -v "$GET_LIST_PREFIX" $CRONTMP >$CRONTMP.2
|
||||
crontab $CRONTMP.2
|
||||
rm -f $CRONTMP.2
|
||||
fi
|
||||
rm -f $CRONTMP
|
||||
}
|
||||
crontab_del_quiet()
|
||||
{
|
||||
exists crontab || return
|
||||
|
||||
CRONTMP=/tmp/cron.tmp
|
||||
crontab -l >$CRONTMP 2>/dev/null
|
||||
if grep -q "$GET_LIST_PREFIX" $CRONTMP; then
|
||||
grep -v "$GET_LIST_PREFIX" $CRONTMP >$CRONTMP.2
|
||||
crontab $CRONTMP.2
|
||||
rm -f $CRONTMP.2
|
||||
fi
|
||||
rm -f $CRONTMP
|
||||
}
|
||||
crontab_add()
|
||||
{
|
||||
# $1 - hour min
|
||||
# $2 - hour max
|
||||
[ -x "$GET_LIST" ] && {
|
||||
echo \* adding crontab entry
|
||||
|
||||
if exists crontab; then
|
||||
CRONTMP=/tmp/cron.tmp
|
||||
crontab -l >$CRONTMP 2>/dev/null
|
||||
if grep -q "$GET_LIST_PREFIX" $CRONTMP; then
|
||||
echo some entries already exist in crontab. check if this is corrent :
|
||||
grep "$GET_LIST_PREFIX" $CRONTMP
|
||||
else
|
||||
end_with_newline <"$CRONTMP" || echo >>"$CRONTMP"
|
||||
echo "$(random 0 59) $(random $1 $2) */2 * * $GET_LIST" >>$CRONTMP
|
||||
crontab $CRONTMP
|
||||
fi
|
||||
rm -f $CRONTMP
|
||||
else
|
||||
echo '!!! CRON IS ABSENT !!! LISTS AUTO UPDATE WILL NOT WORK !!!'
|
||||
fi
|
||||
}
|
||||
}
|
||||
cron_ensure_running()
|
||||
{
|
||||
# if no crontabs present in /etc/cron openwrt init script does not launch crond. this is default
|
||||
[ "$SYSTEM" = "openwrt" ] && {
|
||||
/etc/init.d/cron enable
|
||||
/etc/init.d/cron start
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
service_start_systemd()
|
||||
{
|
||||
echo \* starting zapret2 service
|
||||
|
||||
"$SYSTEMCTL" start zapret2 || {
|
||||
echo could not start zapret2 service
|
||||
exitp 30
|
||||
}
|
||||
}
|
||||
service_stop_systemd()
|
||||
{
|
||||
echo \* stopping zapret2 service
|
||||
|
||||
"$SYSTEMCTL" daemon-reload
|
||||
"$SYSTEMCTL" disable zapret2
|
||||
"$SYSTEMCTL" stop zapret2
|
||||
}
|
||||
service_remove_systemd()
|
||||
{
|
||||
echo \* removing zapret2 service
|
||||
|
||||
rm -f "$SYSTEMD_SYSTEM_DIR/zapret2.service"
|
||||
"$SYSTEMCTL" daemon-reload
|
||||
}
|
||||
timer_remove_systemd()
|
||||
{
|
||||
echo \* removing zapret2-list-update timer
|
||||
|
||||
"$SYSTEMCTL" daemon-reload
|
||||
"$SYSTEMCTL" disable zapret2-list-update.timer
|
||||
"$SYSTEMCTL" stop zapret2-list-update.timer
|
||||
rm -f "$SYSTEMD_SYSTEM_DIR/zapret2-list-update.service" "$SYSTEMD_SYSTEM_DIR/zapret2-list-update.timer"
|
||||
"$SYSTEMCTL" daemon-reload
|
||||
}
|
||||
|
||||
install_sysv_init()
|
||||
{
|
||||
# $1 - "0"=disable
|
||||
echo \* installing init script
|
||||
|
||||
[ -x "$INIT_SCRIPT" ] && {
|
||||
"$INIT_SCRIPT" stop
|
||||
"$INIT_SCRIPT" disable
|
||||
}
|
||||
ln -fs "$INIT_SCRIPT_SRC" "$INIT_SCRIPT"
|
||||
[ "$1" != "0" ] && "$INIT_SCRIPT" enable
|
||||
}
|
||||
install_openrc_init()
|
||||
{
|
||||
# $1 - "0"=disable
|
||||
echo \* installing init script
|
||||
|
||||
[ -x "$INIT_SCRIPT" ] && {
|
||||
"$INIT_SCRIPT" stop
|
||||
rc-update del zapret2
|
||||
}
|
||||
ln -fs "$INIT_SCRIPT_SRC" "$INIT_SCRIPT"
|
||||
[ "$1" != "0" ] && rc-update add zapret2
|
||||
}
|
||||
service_remove_openrc()
|
||||
{
|
||||
echo \* removing zapret2 service
|
||||
|
||||
[ -x "$INIT_SCRIPT" ] && {
|
||||
rc-update del zapret2
|
||||
"$INIT_SCRIPT" stop
|
||||
}
|
||||
rm -f "$INIT_SCRIPT"
|
||||
}
|
||||
service_start_sysv()
|
||||
{
|
||||
[ -x "$INIT_SCRIPT" ] && {
|
||||
echo \* starting zapret2 service
|
||||
"$INIT_SCRIPT" start || {
|
||||
echo could not start zapret2 service
|
||||
exitp 30
|
||||
}
|
||||
}
|
||||
}
|
||||
service_stop_sysv()
|
||||
{
|
||||
[ -x "$INIT_SCRIPT" ] && {
|
||||
echo \* stopping zapret2 service
|
||||
"$INIT_SCRIPT" stop
|
||||
}
|
||||
}
|
||||
service_remove_sysv()
|
||||
{
|
||||
echo \* removing zapret2 service
|
||||
|
||||
[ -x "$INIT_SCRIPT" ] && {
|
||||
"$INIT_SCRIPT" disable
|
||||
"$INIT_SCRIPT" stop
|
||||
}
|
||||
rm -f "$INIT_SCRIPT"
|
||||
}
|
||||
|
||||
check_kmod()
|
||||
{
|
||||
[ -f "/lib/modules/$(uname -r)/$1.ko" ]
|
||||
}
|
||||
check_package_exists_openwrt()
|
||||
{
|
||||
[ -n "$($OPENWRT_PACKAGER list $1)" ]
|
||||
}
|
||||
check_package_openwrt()
|
||||
{
|
||||
case $OPENWRT_PACKAGER in
|
||||
opkg)
|
||||
[ -n "$(opkg list-installed $1)" ] && return 0
|
||||
local what="$(opkg whatprovides $1 | tail -n +2 | head -n 1)"
|
||||
[ -n "$what" ] || return 1
|
||||
[ -n "$(opkg list-installed $what)" ]
|
||||
;;
|
||||
apk)
|
||||
apk info -e $1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
check_packages_openwrt()
|
||||
{
|
||||
for pkg in $@; do
|
||||
check_package_openwrt $pkg || return
|
||||
done
|
||||
}
|
||||
|
||||
install_openwrt_iface_hook()
|
||||
{
|
||||
echo \* installing ifup hook
|
||||
|
||||
ln -fs "$OPENWRT_IFACE_HOOK" /etc/hotplug.d/iface
|
||||
}
|
||||
remove_openwrt_iface_hook()
|
||||
{
|
||||
echo \* removing ifup hook
|
||||
|
||||
rm -f /etc/hotplug.d/iface/??-zapret2
|
||||
}
|
||||
openwrt_fw_section_find()
|
||||
{
|
||||
# $1 - fw include postfix
|
||||
# echoes section number
|
||||
|
||||
i=0
|
||||
while true
|
||||
do
|
||||
path=$(uci -q get firewall.@include[$i].path)
|
||||
[ -n "$path" ] || break
|
||||
[ "$path" = "$OPENWRT_FW_INCLUDE$1" ] && {
|
||||
echo $i
|
||||
return 0
|
||||
}
|
||||
i=$(($i+1))
|
||||
done
|
||||
return 1
|
||||
}
|
||||
openwrt_fw_section_del()
|
||||
{
|
||||
# $1 - fw include postfix
|
||||
|
||||
local id="$(openwrt_fw_section_find $1)"
|
||||
[ -n "$id" ] && {
|
||||
uci delete firewall.@include[$id] && uci commit firewall
|
||||
rm -f "$OPENWRT_FW_INCLUDE$1"
|
||||
}
|
||||
}
|
||||
openwrt_fw_section_add()
|
||||
{
|
||||
openwrt_fw_section_find ||
|
||||
{
|
||||
uci add firewall include >/dev/null || return
|
||||
echo -1
|
||||
}
|
||||
}
|
||||
openwrt_fw_section_configure()
|
||||
{
|
||||
local id="$(openwrt_fw_section_add $1)"
|
||||
[ -z "$id" ] ||
|
||||
! uci set firewall.@include[$id].path="$OPENWRT_FW_INCLUDE" ||
|
||||
! uci set firewall.@include[$id].reload="1" ||
|
||||
! uci commit firewall &&
|
||||
{
|
||||
echo could not add firewall include
|
||||
exitp 50
|
||||
}
|
||||
}
|
||||
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"
|
||||
|
||||
openwrt_fw_section_configure $1
|
||||
}
|
||||
restart_openwrt_firewall()
|
||||
{
|
||||
echo \* restarting firewall
|
||||
|
||||
local FW=fw4
|
||||
[ -n "$OPENWRT_FW3" ] && FW=fw3
|
||||
exists $FW && $FW -q restart || {
|
||||
echo could not restart firewall $FW
|
||||
}
|
||||
}
|
||||
remove_openwrt_firewall()
|
||||
{
|
||||
echo \* removing firewall script
|
||||
|
||||
openwrt_fw_section_del
|
||||
}
|
||||
|
||||
clear_ipset()
|
||||
{
|
||||
echo "* clearing ipset(s)"
|
||||
|
||||
# free some RAM
|
||||
"$IPSET_DIR/create_ipset.sh" clear
|
||||
}
|
||||
|
||||
|
||||
|
||||
write_config_var()
|
||||
{
|
||||
# $1 - mode var
|
||||
local M
|
||||
eval M="\$$1"
|
||||
# replace / => \/
|
||||
#M=${M//\//\\\/}
|
||||
M=$(echo $M | sed 's/\//\\\//g' | trim)
|
||||
grep -q "^[[:space:]]*$1=\|^#*[[:space:]]*$1=" "$ZAPRET_CONFIG" || {
|
||||
# var does not exist in config. add it
|
||||
echo $1= >>"$ZAPRET_CONFIG"
|
||||
}
|
||||
replace_var_def $1 "$M" "$ZAPRET_CONFIG"
|
||||
}
|
||||
|
||||
no_prereq_exit()
|
||||
{
|
||||
echo could not install prerequisites
|
||||
exitp 6
|
||||
}
|
||||
check_prerequisites_linux()
|
||||
{
|
||||
echo \* checking prerequisites
|
||||
|
||||
local s cmd PKGS UTILS req="curl curl"
|
||||
local APTGET DNF YUM PACMAN ZYPPER EOPKG APK
|
||||
case "$FWTYPE" in
|
||||
iptables)
|
||||
req="$req iptables iptables ip6tables iptables ipset ipset"
|
||||
;;
|
||||
nftables)
|
||||
req="$req nft nftables"
|
||||
;;
|
||||
esac
|
||||
|
||||
PKGS=$(for s in $req; do echo $s; done |
|
||||
while read cmd; do
|
||||
read pkg
|
||||
exists $cmd || echo $pkg
|
||||
done | sort -u | xargs)
|
||||
UTILS=$(for s in $req; do echo $s; done |
|
||||
while read cmd; do
|
||||
read pkg
|
||||
echo $cmd
|
||||
done | sort -u | xargs)
|
||||
|
||||
if [ -z "$PKGS" ] ; then
|
||||
echo required utilities exist : $UTILS
|
||||
else
|
||||
echo \* installing prerequisites
|
||||
|
||||
echo packages required : $PKGS
|
||||
|
||||
APTGET=$(whichq apt-get)
|
||||
DNF=$(whichq dnf)
|
||||
YUM=$(whichq yum)
|
||||
PACMAN=$(whichq pacman)
|
||||
ZYPPER=$(whichq zypper)
|
||||
EOPKG=$(whichq eopkg)
|
||||
APK=$(whichq apk)
|
||||
if [ -x "$APTGET" ] ; then
|
||||
"$APTGET" update
|
||||
"$APTGET" install -y --no-install-recommends $PKGS dnsutils || no_prereq_exit
|
||||
elif [ -x "$DNF" ] ; then
|
||||
"$DNF" -y install $PKGS || no_prereq_exit
|
||||
elif [ -x "$YUM" ] ; then
|
||||
"$YUM" -y install $PKGS || no_prereq_exit
|
||||
elif [ -x "$PACMAN" ] ; then
|
||||
"$PACMAN" -Syy
|
||||
"$PACMAN" --noconfirm -S $PKGS || no_prereq_exit
|
||||
elif [ -x "$ZYPPER" ] ; then
|
||||
"$ZYPPER" --non-interactive install $PKGS || no_prereq_exit
|
||||
elif [ -x "$EOPKG" ] ; then
|
||||
"$EOPKG" -y install $PKGS || no_prereq_exit
|
||||
elif [ -x "$APK" ] ; then
|
||||
"$APK" update
|
||||
# for alpine
|
||||
[ "$FWTYPE" = iptables ] && [ -n "$($APK list ip6tables)" ] && PKGS="$PKGS ip6tables"
|
||||
"$APK" add $PKGS || no_prereq_exit
|
||||
else
|
||||
echo supported package manager not found
|
||||
echo you must manually install : $UTILS
|
||||
exitp 5
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
removable_pkgs_openwrt()
|
||||
{
|
||||
local pkg PKGS2
|
||||
[ -n "$OPENWRT_FW4" ] && PKGS2="$PKGS2 iptables-zz-legacy iptables ip6tables-zz-legacy ip6tables"
|
||||
[ -n "$OPENWRT_FW3" ] && PKGS2="$PKGS2 nftables-json nftables-nojson nftables"
|
||||
PKGS=
|
||||
for pkg in $PKGS2; do
|
||||
check_package_exists_openwrt $pkg && PKGS="${PKGS:+$PKGS }$pkg"
|
||||
done
|
||||
PKGS="ipset iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra iptables-mod-u32 ip6tables-mod-nat ip6tables-extra kmod-nft-queue gzip coreutils-sort coreutils-sleep curl $PKGS"
|
||||
}
|
||||
|
||||
openwrt_fix_broken_apk_uninstall_scripts()
|
||||
{
|
||||
# at least in early snapshots with apk removing gnu gzip, sort, ... does not restore links to busybox
|
||||
# system may become unusable
|
||||
exists sort || { echo fixing missing sort; ln -fs /bin/busybox /usr/bin/sort; }
|
||||
exists gzip || { echo fixing missing gzip; ln -fs /bin/busybox /bin/gzip; }
|
||||
exists sleep || { echo fixing missing sleep; ln -fs /bin/busybox /bin/sleep; }
|
||||
}
|
||||
|
||||
remove_extra_pkgs_openwrt()
|
||||
{
|
||||
local PKGS
|
||||
echo \* remove dependencies
|
||||
removable_pkgs_openwrt
|
||||
echo these packages may have been installed by install_easy.sh : $PKGS
|
||||
ask_yes_no N "do you want to remove them" && {
|
||||
case $OPENWRT_PACKAGER in
|
||||
opkg)
|
||||
opkg remove --autoremove $PKGS
|
||||
;;
|
||||
apk)
|
||||
apk del $PKGS
|
||||
openwrt_fix_broken_apk_uninstall_scripts
|
||||
;;
|
||||
esac
|
||||
}
|
||||
}
|
||||
|
||||
check_prerequisites_openwrt()
|
||||
{
|
||||
echo \* checking prerequisites
|
||||
|
||||
local PKGS="curl" UPD=0 local pkg_iptables
|
||||
|
||||
case "$FWTYPE" in
|
||||
iptables)
|
||||
pkg_iptables=iptables
|
||||
check_package_exists_openwrt iptables-zz-legacy && pkg_iptables=iptables-zz-legacy
|
||||
PKGS="$PKGS ipset $pkg_iptables iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra iptables-mod-u32"
|
||||
check_package_exists_openwrt ip6tables-zz-legacy && pkg_iptables=ip6tables-zz-legacy
|
||||
[ "$DISABLE_IPV6" = 1 ] || PKGS="$PKGS $pkg_iptables ip6tables-mod-nat ip6tables-extra"
|
||||
;;
|
||||
nftables)
|
||||
PKGS="$PKGS nftables kmod-nft-nat kmod-nft-offload kmod-nft-queue"
|
||||
;;
|
||||
esac
|
||||
|
||||
if check_packages_openwrt $PKGS ; then
|
||||
echo everything is present
|
||||
else
|
||||
echo \* installing prerequisites
|
||||
|
||||
$OPENWRT_PACKAGER_UPDATE
|
||||
UPD=1
|
||||
$OPENWRT_PACKAGER_INSTALL $PKGS || {
|
||||
echo could not install prerequisites
|
||||
exitp 6
|
||||
}
|
||||
fi
|
||||
|
||||
is_linked_to_busybox gzip && {
|
||||
echo
|
||||
echo your system uses default busybox gzip. its several times slower than GNU gzip.
|
||||
echo ip/host list scripts will run much faster with GNU gzip
|
||||
echo installer can install GNU gzip but it requires about 100 Kb space
|
||||
if ask_yes_no N "do you want to install GNU gzip"; then
|
||||
[ "$UPD" = "0" ] && {
|
||||
$OPENWRT_PACKAGER_UPDATE
|
||||
UPD=1
|
||||
}
|
||||
$OPENWRT_PACKAGER_INSTALL --force-overwrite gzip
|
||||
fi
|
||||
}
|
||||
is_linked_to_busybox sort && {
|
||||
echo
|
||||
echo your system uses default busybox sort. its much slower and consumes much more RAM than GNU sort
|
||||
echo ip/host list scripts will run much faster with GNU sort
|
||||
echo installer can install GNU sort but it requires about 100 Kb space
|
||||
if ask_yes_no N "do you want to install GNU sort"; then
|
||||
[ "$UPD" = "0" ] && {
|
||||
$OPENWRT_PACKAGER_UPDATE
|
||||
UPD=1
|
||||
}
|
||||
$OPENWRT_PACKAGER_INSTALL --force-overwrite coreutils-sort
|
||||
fi
|
||||
}
|
||||
[ "$FSLEEP" = 0 ] && is_linked_to_busybox sleep && {
|
||||
echo
|
||||
echo no methods of sub-second sleep were found.
|
||||
echo if you want to speed up blockcheck install coreutils-sleep. it requires about 40 Kb space
|
||||
if ask_yes_no N "do you want to install COREUTILS sleep"; then
|
||||
[ "$UPD" = "0" ] && {
|
||||
$OPENWRT_PACKAGER_UPDATE
|
||||
UPD=1
|
||||
}
|
||||
$OPENWRT_PACKAGER_INSTALL --force-overwrite coreutils-sleep
|
||||
fsleep_setup
|
||||
fi
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
select_ipv6()
|
||||
{
|
||||
local T=N
|
||||
|
||||
[ "$DISABLE_IPV6" != '1' ] && T=Y
|
||||
local old6=$DISABLE_IPV6
|
||||
echo
|
||||
if ask_yes_no $T "enable ipv6 support"; then
|
||||
DISABLE_IPV6=0
|
||||
else
|
||||
DISABLE_IPV6=1
|
||||
fi
|
||||
[ "$old6" != "$DISABLE_IPV6" ] && write_config_var DISABLE_IPV6
|
||||
}
|
||||
select_fwtype()
|
||||
{
|
||||
echo
|
||||
[ $(get_ram_mb) -le 400 ] && {
|
||||
echo WARNING ! you are running a low RAM system
|
||||
echo WARNING ! nft requires lots of RAM to load huge ip sets, much more than ipsets require
|
||||
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
|
||||
}
|
||||
|
||||
dry_run_nfqws_()
|
||||
{
|
||||
local NFQWS="$ZAPRET_BASE/nfq2/nfqws2"
|
||||
echo verifying nfqws options
|
||||
"$NFQWS" --dry-run ${WS_USER:+--user=$WS_USER} "$@"
|
||||
}
|
||||
dry_run_nfqws()
|
||||
{
|
||||
[ "$NFQWS2_ENABLE" = 1 ] || return 0
|
||||
local opt="$NFQWS2_OPT" qn=${QNUM:-300}
|
||||
filter_apply_hostlist_target opt
|
||||
dry_run_nfqws_ --qnum=$qn $opt
|
||||
echo NOTE ! LUA code validity cannot be verified at this stage !
|
||||
}
|
||||
331
common/ipt.sh
Normal file
331
common/ipt.sh
Normal file
@@ -0,0 +1,331 @@
|
||||
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"
|
||||
|
||||
ipt()
|
||||
{
|
||||
iptables $FW_EXTRA_PRE -C "$@" $FW_EXTRA_POST >/dev/null 2>/dev/null || iptables $FW_EXTRA_PRE -I "$@" $FW_EXTRA_POST
|
||||
}
|
||||
ipta()
|
||||
{
|
||||
iptables $FW_EXTRA_PRE -C "$@" $FW_EXTRA_POST >/dev/null 2>/dev/null || iptables $FW_EXTRA_PRE -A "$@" $FW_EXTRA_POST
|
||||
}
|
||||
ipt_del()
|
||||
{
|
||||
iptables $FW_EXTRA_PRE -C "$@" $FW_EXTRA_POST >/dev/null 2>/dev/null && iptables $FW_EXTRA_PRE -D "$@" $FW_EXTRA_POST
|
||||
}
|
||||
ipt_add_del()
|
||||
{
|
||||
on_off_function ipt ipt_del "$@"
|
||||
}
|
||||
ipta_add_del()
|
||||
{
|
||||
on_off_function ipta ipt_del "$@"
|
||||
}
|
||||
ipt6()
|
||||
{
|
||||
ip6tables -C "$@" >/dev/null 2>/dev/null || ip6tables -I "$@"
|
||||
}
|
||||
ipt6a()
|
||||
{
|
||||
ip6tables -C "$@" >/dev/null 2>/dev/null || ip6tables -A "$@"
|
||||
}
|
||||
ipt6_del()
|
||||
{
|
||||
ip6tables -C "$@" >/dev/null 2>/dev/null && ip6tables -D "$@"
|
||||
}
|
||||
ipt6_add_del()
|
||||
{
|
||||
on_off_function ipt6 ipt6_del "$@"
|
||||
}
|
||||
ipt6a_add_del()
|
||||
{
|
||||
on_off_function ipt6 ipt6a_del "$@"
|
||||
}
|
||||
|
||||
is_ipt_flow_offload_avail()
|
||||
{
|
||||
# $1 = '' for ipv4, '6' for ipv6
|
||||
grep -q FLOWOFFLOAD 2>/dev/null /proc/net/ip$1_tables_targets
|
||||
}
|
||||
|
||||
filter_apply_ipset_target4()
|
||||
{
|
||||
# $1 - var name of ipv4 iptables filter
|
||||
if [ "$MODE_FILTER" = "ipset" ]; then
|
||||
eval $1="\"\$$1 -m set --match-set zapret dst\""
|
||||
fi
|
||||
}
|
||||
filter_apply_ipset_target6()
|
||||
{
|
||||
# $1 - var name of ipv6 iptables filter
|
||||
if [ "$MODE_FILTER" = "ipset" ]; then
|
||||
eval $1="\"\$$1 -m set --match-set zapret6 dst\""
|
||||
fi
|
||||
}
|
||||
filter_apply_ipset_target()
|
||||
{
|
||||
# $1 - var name of ipv4 iptables filter
|
||||
# $2 - var name of ipv6 iptables filter
|
||||
filter_apply_ipset_target4 $1
|
||||
filter_apply_ipset_target6 $2
|
||||
}
|
||||
|
||||
reverse_nfqws_rule_stream()
|
||||
{
|
||||
sed -e 's/-o /-i /g' -e 's/--dport /--sport /g' -e 's/--dports /--sports /g' -e 's/ dst$/ src/' -e 's/ dst / src /g' -e 's/--connbytes-dir=original/--connbytes-dir=reply/g' -e "s/-m mark ! --mark $DESYNC_MARK\/$DESYNC_MARK//g"
|
||||
}
|
||||
reverse_nfqws_rule()
|
||||
{
|
||||
echo "$@" | reverse_nfqws_rule_stream
|
||||
}
|
||||
|
||||
ipt_mark_filter()
|
||||
{
|
||||
[ -n "$FILTER_MARK" ] && echo "-m mark --mark $FILTER_MARK/$FILTER_MARK"
|
||||
}
|
||||
|
||||
ipt_print_op()
|
||||
{
|
||||
if [ "$1" = "1" ]; then
|
||||
echo "Inserting ip$4tables rule for $3 : $2"
|
||||
else
|
||||
echo "Deleting ip$4tables rule for $3 : $2"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
_fw_nfqws_post4()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - iptable filter for ipv4
|
||||
# $3 - queue number
|
||||
# $4 - wan interface names space separated
|
||||
[ "$DISABLE_IPV4" = "1" -o -z "$2" ] || {
|
||||
local i
|
||||
|
||||
ipt_print_op $1 "$2" "nfqws postrouting (qnum $3)"
|
||||
|
||||
rule="$(ipt_mark_filter) -m mark ! --mark $DESYNC_MARK/$DESYNC_MARK $2 $IPSET_EXCLUDE dst -j NFQUEUE --queue-num $3 --queue-bypass"
|
||||
if [ -n "$4" ] ; then
|
||||
for i in $4; do
|
||||
ipt_add_del $1 POSTROUTING -t mangle -o $i $rule
|
||||
done
|
||||
else
|
||||
ipt_add_del $1 POSTROUTING -t mangle $rule
|
||||
fi
|
||||
}
|
||||
}
|
||||
_fw_nfqws_post6()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - iptable filter for ipv6
|
||||
# $3 - queue number
|
||||
# $4 - wan interface names space separated
|
||||
[ "$DISABLE_IPV6" = "1" -o -z "$2" ] || {
|
||||
local i
|
||||
|
||||
ipt_print_op $1 "$2" "nfqws postrouting (qnum $3)" 6
|
||||
|
||||
rule="$(ipt_mark_filter) -m mark ! --mark $DESYNC_MARK/$DESYNC_MARK $2 $IPSET_EXCLUDE6 dst -j NFQUEUE --queue-num $3 --queue-bypass"
|
||||
if [ -n "$4" ] ; then
|
||||
for i in $4; do
|
||||
ipt6_add_del $1 POSTROUTING -t mangle -o $i $rule
|
||||
done
|
||||
else
|
||||
ipt6_add_del $1 POSTROUTING -t mangle $rule
|
||||
fi
|
||||
}
|
||||
}
|
||||
fw_nfqws_post()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - iptable filter for ipv4
|
||||
# $3 - iptable filter for ipv6
|
||||
# $4 - queue number
|
||||
fw_nfqws_post4 $1 "$2" $4
|
||||
fw_nfqws_post6 $1 "$3" $4
|
||||
}
|
||||
|
||||
_fw_nfqws_pre4()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - iptable filter for ipv4
|
||||
# $3 - queue number
|
||||
# $4 - wan interface names space separated
|
||||
[ "$DISABLE_IPV4" = "1" -o -z "$2" ] || {
|
||||
local i
|
||||
|
||||
ipt_print_op $1 "$2" "nfqws input+forward (qnum $3)"
|
||||
|
||||
rule="$2 $IPSET_EXCLUDE src -j NFQUEUE --queue-num $3 --queue-bypass"
|
||||
if [ -n "$4" ] ; then
|
||||
for i in $4; do
|
||||
# iptables PREROUTING chain is before NAT. not possible to have DNATed ip's there
|
||||
ipt_add_del $1 INPUT -t mangle -i $i $rule
|
||||
ipt_add_del $1 FORWARD -t mangle -i $i $rule
|
||||
done
|
||||
else
|
||||
ipt_add_del $1 INPUT -t mangle $rule
|
||||
ipt_add_del $1 FORWARD -t mangle $rule
|
||||
fi
|
||||
}
|
||||
}
|
||||
_fw_nfqws_pre6()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - iptable filter for ipv6
|
||||
# $3 - queue number
|
||||
# $4 - wan interface names space separated
|
||||
[ "$DISABLE_IPV6" = "1" -o -z "$2" ] || {
|
||||
local i
|
||||
|
||||
ipt_print_op $1 "$2" "nfqws input+forward (qnum $3)" 6
|
||||
|
||||
rule="$2 $IPSET_EXCLUDE6 src -j NFQUEUE --queue-num $3 --queue-bypass"
|
||||
if [ -n "$4" ] ; then
|
||||
for i in $4; do
|
||||
# iptables PREROUTING chain is before NAT. not possible to have DNATed ip's there
|
||||
ipt6_add_del $1 INPUT -t mangle -i $i $rule
|
||||
ipt6_add_del $1 FORWARD -t mangle -i $i $rule
|
||||
done
|
||||
else
|
||||
ipt6_add_del $1 INPUT -t mangle $rule
|
||||
ipt6_add_del $1 FORWARD -t mangle $rule
|
||||
fi
|
||||
}
|
||||
}
|
||||
fw_nfqws_pre()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - iptable filter for ipv4
|
||||
# $3 - iptable filter for ipv6
|
||||
# $4 - queue number
|
||||
fw_nfqws_pre4 $1 "$2" $4
|
||||
fw_nfqws_pre6 $1 "$3" $4
|
||||
}
|
||||
|
||||
|
||||
fw_reverse_nfqws_rule4()
|
||||
{
|
||||
fw_nfqws_pre4 $1 "$(reverse_nfqws_rule "$2")" $3
|
||||
}
|
||||
fw_reverse_nfqws_rule6()
|
||||
{
|
||||
fw_nfqws_pre6 $1 "$(reverse_nfqws_rule "$2")" $3
|
||||
}
|
||||
fw_reverse_nfqws_rule()
|
||||
{
|
||||
# ensure that modes relying on incoming traffic work
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - rule4
|
||||
# $3 - rule6
|
||||
# $4 - queue number
|
||||
fw_reverse_nfqws_rule4 $1 "$2" $4
|
||||
fw_reverse_nfqws_rule6 $1 "$3" $4
|
||||
}
|
||||
|
||||
ipt_first_packets()
|
||||
{
|
||||
# $1 - packet count
|
||||
[ -n "$1" -a "$1" != keepalive ] && [ "$1" -ge 1 ] && echo "$ipt_connbytes 1:$1"
|
||||
}
|
||||
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
|
||||
[ -n "$3" ] || return
|
||||
[ -n "$4" -a "$4" != 0 ] &&
|
||||
{
|
||||
first_packets_only="$(ipt_first_packets $4)"
|
||||
f4="-p $2 -m multiport --dports $3 $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
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
||||
zapret_do_firewall_standard_rules_ipt()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
|
||||
zapret_do_firewall_standard_nfqws_rules_ipt $1
|
||||
}
|
||||
|
||||
zapret_do_firewall_rules_ipt()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
|
||||
zapret_do_firewall_standard_rules_ipt $1
|
||||
custom_runner zapret_custom_firewall $1
|
||||
zapret_do_icmp_filter $1
|
||||
}
|
||||
|
||||
zapret_do_icmp_filter()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
|
||||
local FW_EXTRA_PRE= FW_EXTRA_POST=
|
||||
|
||||
[ "$FILTER_TTL_EXPIRED_ICMP" = 1 ] && {
|
||||
[ "$DISABLE_IPV4" = 1 ] || {
|
||||
ipt_add_del $1 POSTROUTING -t mangle -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j CONNMARK --or-mark $DESYNC_MARK
|
||||
ipt_add_del $1 INPUT -p icmp -m icmp --icmp-type time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
|
||||
ipt_add_del $1 FORWARD -p icmp -m icmp --icmp-type time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
|
||||
}
|
||||
[ "$DISABLE_IPV6" = 1 ] || {
|
||||
ipt6_add_del $1 POSTROUTING -t mangle -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j CONNMARK --or-mark $DESYNC_MARK
|
||||
ipt6_add_del $1 INPUT -p icmpv6 -m icmp6 --icmpv6-type time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
|
||||
ipt6_add_del $1 FORWARD -p icmpv6 -m icmp6 --icmpv6-type time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zapret_do_firewall_ipt()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
|
||||
if [ "$1" = 1 ]; then
|
||||
echo Applying iptables
|
||||
else
|
||||
echo Clearing iptables
|
||||
fi
|
||||
|
||||
# always create ipsets. ip_exclude ipset is required
|
||||
[ "$1" = 1 ] && create_ipset no-update
|
||||
|
||||
zapret_do_firewall_rules_ipt "$@"
|
||||
|
||||
if [ "$1" = 1 ] ; then
|
||||
existf flow_offloading_exempt && flow_offloading_exempt
|
||||
else
|
||||
existf flow_offloading_unexempt && flow_offloading_unexempt
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
33
common/linux_daemons.sh
Normal file
33
common/linux_daemons.sh
Normal file
@@ -0,0 +1,33 @@
|
||||
standard_mode_nfqws()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
local opt
|
||||
[ "$NFQWS2_ENABLE" = 1 ] && check_bad_ws_options $1 "$NFQWS2_OPT" && {
|
||||
opt="--qnum=$QNUM $NFQWS2_OPT"
|
||||
filter_apply_hostlist_target opt
|
||||
do_nfqws $1 1 "$opt"
|
||||
}
|
||||
}
|
||||
standard_mode_daemons()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
standard_mode_nfqws $1
|
||||
}
|
||||
zapret_do_daemons()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
standard_mode_daemons $1
|
||||
custom_runner zapret_custom_daemons $1
|
||||
|
||||
return 0
|
||||
}
|
||||
zapret_run_daemons()
|
||||
{
|
||||
zapret_do_daemons 1 "$@"
|
||||
}
|
||||
zapret_stop_daemons()
|
||||
{
|
||||
zapret_do_daemons 0 "$@"
|
||||
}
|
||||
40
common/linux_fw.sh
Normal file
40
common/linux_fw.sh
Normal file
@@ -0,0 +1,40 @@
|
||||
set_conntrack_liberal_mode()
|
||||
{
|
||||
[ -n "$SKIP_CONNTRACK_LIBERAL_MODE" ] || sysctl -w net.netfilter.nf_conntrack_tcp_be_liberal=$1
|
||||
}
|
||||
zapret_do_firewall()
|
||||
{
|
||||
linux_fwtype
|
||||
|
||||
[ "$1" = 1 -a -n "$INIT_FW_PRE_UP_HOOK" ] && $INIT_FW_PRE_UP_HOOK
|
||||
[ "$1" = 0 -a -n "$INIT_FW_PRE_DOWN_HOOK" ] && $INIT_FW_PRE_DOWN_HOOK
|
||||
|
||||
case "$FWTYPE" in
|
||||
iptables)
|
||||
zapret_do_firewall_ipt "$@"
|
||||
;;
|
||||
nftables)
|
||||
zapret_do_firewall_nft "$@"
|
||||
;;
|
||||
esac
|
||||
|
||||
# russian DPI sends RST,ACK with wrong ACK.
|
||||
# this is sometimes treated by conntrack as invalid and connbytes fw rules do not pass RST packet to nfqws.
|
||||
# switch on liberal mode on zapret firewall start and switch off on zapret firewall stop
|
||||
# this is only required for processing incoming bad RSTs. incoming rules are only applied in autohostlist mode
|
||||
# calling this after firewall because conntrack module can be not loaded before applying conntrack firewall rules
|
||||
[ "$MODE_FILTER" = "autohostlist" ] && set_conntrack_liberal_mode $1
|
||||
|
||||
[ "$1" = 1 -a -n "$INIT_FW_POST_UP_HOOK" ] && $INIT_FW_POST_UP_HOOK
|
||||
[ "$1" = 0 -a -n "$INIT_FW_POST_DOWN_HOOK" ] && $INIT_FW_POST_DOWN_HOOK
|
||||
|
||||
return 0
|
||||
}
|
||||
zapret_apply_firewall()
|
||||
{
|
||||
zapret_do_firewall 1 "$@"
|
||||
}
|
||||
zapret_unapply_firewall()
|
||||
{
|
||||
zapret_do_firewall 0 "$@"
|
||||
}
|
||||
24
common/linux_iphelper.sh
Normal file
24
common/linux_iphelper.sh
Normal file
@@ -0,0 +1,24 @@
|
||||
get_uevent_devtype()
|
||||
{
|
||||
local DEVTYPE INTERFACE IFINDEX OF_NAME OF_FULLNAME OF_COMPATIBLE_N
|
||||
[ -f "/sys/class/net/$1/uevent" ] && {
|
||||
. "/sys/class/net/$1/uevent"
|
||||
echo -n $DEVTYPE
|
||||
}
|
||||
}
|
||||
resolve_lower_devices()
|
||||
{
|
||||
# $1 - bridge interface name
|
||||
[ -d "/sys/class/net/$1" ] && {
|
||||
find "/sys/class/net/$1" -follow -maxdepth 1 -name "lower_*" |
|
||||
{
|
||||
local l lower lowers
|
||||
while read lower; do
|
||||
lower="$(basename "$lower")"
|
||||
l="${lower#lower_*}"
|
||||
[ "$l" != "$lower" ] && append_separator_list lowers ' ' '' "$l"
|
||||
done
|
||||
printf "$lowers"
|
||||
}
|
||||
}
|
||||
}
|
||||
60
common/list.sh
Normal file
60
common/list.sh
Normal file
@@ -0,0 +1,60 @@
|
||||
HOSTLIST_MARKER="<HOSTLIST>"
|
||||
HOSTLIST_NOAUTO_MARKER="<HOSTLIST_NOAUTO>"
|
||||
|
||||
find_hostlists()
|
||||
{
|
||||
[ -n "$HOSTLIST_BASE" ] || HOSTLIST_BASE="$ZAPRET_BASE/ipset"
|
||||
|
||||
HOSTLIST="$HOSTLIST_BASE/zapret-hosts.txt.gz"
|
||||
[ -f "$HOSTLIST" ] || HOSTLIST="$HOSTLIST_BASE/zapret-hosts.txt"
|
||||
[ -f "$HOSTLIST" ] || HOSTLIST=
|
||||
|
||||
HOSTLIST_USER="$HOSTLIST_BASE/zapret-hosts-user.txt.gz"
|
||||
[ -f "$HOSTLIST_USER" ] || HOSTLIST_USER="$HOSTLIST_BASE/zapret-hosts-user.txt"
|
||||
[ -f "$HOSTLIST_USER" ] || HOSTLIST_USER=
|
||||
|
||||
HOSTLIST_EXCLUDE="$HOSTLIST_BASE/zapret-hosts-user-exclude.txt.gz"
|
||||
[ -f "$HOSTLIST_EXCLUDE" ] || HOSTLIST_EXCLUDE="$HOSTLIST_BASE/zapret-hosts-user-exclude.txt"
|
||||
[ -f "$HOSTLIST_EXCLUDE" ] || HOSTLIST_EXCLUDE=
|
||||
|
||||
HOSTLIST_AUTO="$HOSTLIST_BASE/zapret-hosts-auto.txt"
|
||||
HOSTLIST_AUTO_DEBUGLOG="$HOSTLIST_BASE/zapret-hosts-auto-debug.log"
|
||||
}
|
||||
|
||||
filter_apply_hostlist_target()
|
||||
{
|
||||
# $1 - var name of nfqws params
|
||||
|
||||
local v parm parm1 parm2 parm3 parm4 parm5 parm6 parm7 parm8 parm9 parm10 param11 param12 param13 parmNA
|
||||
eval v="\$$1"
|
||||
if contains "$v" "$HOSTLIST_MARKER" || contains "$v" "$HOSTLIST_NOAUTO_MARKER"; then
|
||||
[ "$MODE_FILTER" = hostlist -o "$MODE_FILTER" = autohostlist ] &&
|
||||
{
|
||||
find_hostlists
|
||||
parm1="${HOSTLIST_USER:+--hostlist=$HOSTLIST_USER}"
|
||||
parm2="${HOSTLIST:+--hostlist=$HOSTLIST}"
|
||||
parm3="${HOSTLIST_EXCLUDE:+--hostlist-exclude=$HOSTLIST_EXCLUDE}"
|
||||
[ "$MODE_FILTER" = autohostlist ] &&
|
||||
{
|
||||
parm4="--hostlist-auto=$HOSTLIST_AUTO"
|
||||
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_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}${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")"
|
||||
[ "$MODE_FILTER" = autohostlist -a "$AUTOHOSTLIST_DEBUGLOG" = 1 ] && {
|
||||
v="$v --hostlist-auto-debug=$HOSTLIST_AUTO_DEBUGLOG"
|
||||
}
|
||||
eval $1=\""$v"\"
|
||||
fi
|
||||
}
|
||||
712
common/nft.sh
Normal file
712
common/nft.sh
Normal file
@@ -0,0 +1,712 @@
|
||||
[ -n "$ZAPRET_NFT_TABLE" ] || ZAPRET_NFT_TABLE=zapret2
|
||||
nft_connbytes="ct original packets"
|
||||
|
||||
# required for : nft -f -
|
||||
create_dev_stdin
|
||||
std_ports
|
||||
|
||||
nft_create_table()
|
||||
{
|
||||
nft add table inet $ZAPRET_NFT_TABLE
|
||||
}
|
||||
nft_del_table()
|
||||
{
|
||||
nft delete table inet $ZAPRET_NFT_TABLE 2>/dev/null
|
||||
}
|
||||
nft_list_table()
|
||||
{
|
||||
nft -t list table inet $ZAPRET_NFT_TABLE
|
||||
}
|
||||
|
||||
nft_create_set()
|
||||
{
|
||||
# $1 - set name
|
||||
# $2 - params
|
||||
nft create set inet $ZAPRET_NFT_TABLE $1 "{ $2 }" 2>/dev/null
|
||||
}
|
||||
nft_del_set()
|
||||
{
|
||||
# $1 - set name
|
||||
nft delete set inet $ZAPRET_NFT_TABLE $1
|
||||
}
|
||||
nft_flush_set()
|
||||
{
|
||||
# $1 - set name
|
||||
nft flush set inet $ZAPRET_NFT_TABLE $1
|
||||
}
|
||||
nft_flush_chain()
|
||||
{
|
||||
# $1 - set name
|
||||
nft flush chain inet $ZAPRET_NFT_TABLE $1
|
||||
}
|
||||
nft_set_exists()
|
||||
{
|
||||
# $1 - set name
|
||||
nft -t list set inet $ZAPRET_NFT_TABLE $1 2>/dev/null >/dev/null
|
||||
}
|
||||
nft_flush_chain()
|
||||
{
|
||||
# $1 - chain name
|
||||
nft flush chain inet $ZAPRET_NFT_TABLE $1
|
||||
}
|
||||
nft_chain_empty()
|
||||
{
|
||||
# $1 - chain name
|
||||
local count=$(nft list chain inet $ZAPRET_NFT_TABLE prerouting | wc -l)
|
||||
[ "$count" -le 4 ]
|
||||
}
|
||||
nft_rule_exists()
|
||||
{
|
||||
# $1 - chain
|
||||
# $2 - rule
|
||||
local rule
|
||||
# convert rule to nft output form
|
||||
nft_flush_chain ruletest
|
||||
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_del_all_chains_from_table()
|
||||
{
|
||||
# $1 - table_name with or without family
|
||||
|
||||
# delete all chains with possible references to each other
|
||||
# cannot just delete all in the list because of references
|
||||
# avoid infinite loops
|
||||
local chains deleted=1 error=1
|
||||
while [ -n "$deleted" -a -n "$error" ]; do
|
||||
chains=$(nft -t list table $1 2>/dev/null | sed -nre "s/^[ ]*chain ([^ ]+) \{/\1/p" | xargs)
|
||||
[ -n "$chains" ] || break
|
||||
deleted=
|
||||
error=
|
||||
for chain in $chains; do
|
||||
if nft delete chain $1 $chain 2>/dev/null; then
|
||||
deleted=1
|
||||
else
|
||||
error=1
|
||||
fi
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
# ipset checks cost some CPU. do not populate jump from hook until something is added to the chain
|
||||
nft_activate_chain4()
|
||||
{
|
||||
# $1 - chain name
|
||||
# $2 - saddr/daddr
|
||||
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 $flt_ifname @wanif"
|
||||
rule="$rule ip $2 != @nozapret jump $1"
|
||||
nft_rule_exists ${1}_hook "$rule" || nft_add_rule ${1}_hook $rule
|
||||
|
||||
eval ${1}_act4=1
|
||||
}
|
||||
}
|
||||
nft_activate_chain6()
|
||||
{
|
||||
# $1 - chain name
|
||||
# $2 - saddr/daddr
|
||||
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 $flt_ifname @wanif6"
|
||||
rule="$rule ip6 $2 != @nozapret6 jump $1"
|
||||
nft_rule_exists ${1}_hook "$rule" || nft_add_rule ${1}_hook $rule
|
||||
|
||||
eval ${1}_act6=1
|
||||
}
|
||||
}
|
||||
|
||||
nft_create_chains()
|
||||
{
|
||||
cat << EOF | nft -f -
|
||||
add chain inet $ZAPRET_NFT_TABLE forward_hook { type filter hook forward priority -1; }
|
||||
flush chain inet $ZAPRET_NFT_TABLE forward_hook
|
||||
|
||||
add chain inet $ZAPRET_NFT_TABLE flow_offload
|
||||
flush chain inet $ZAPRET_NFT_TABLE flow_offload
|
||||
add chain inet $ZAPRET_NFT_TABLE flow_offload_zapret
|
||||
flush chain inet $ZAPRET_NFT_TABLE flow_offload_zapret
|
||||
add chain inet $ZAPRET_NFT_TABLE flow_offload_always
|
||||
flush chain inet $ZAPRET_NFT_TABLE flow_offload_always
|
||||
|
||||
add chain inet $ZAPRET_NFT_TABLE postrouting
|
||||
flush chain inet $ZAPRET_NFT_TABLE postrouting
|
||||
add chain inet $ZAPRET_NFT_TABLE postrouting_hook { type filter hook postrouting priority 99; }
|
||||
flush chain inet $ZAPRET_NFT_TABLE postrouting_hook
|
||||
|
||||
add chain inet $ZAPRET_NFT_TABLE postnat
|
||||
flush chain inet $ZAPRET_NFT_TABLE postnat
|
||||
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 prenat_hook { type filter hook prerouting priority -101; }
|
||||
flush chain inet $ZAPRET_NFT_TABLE prenat_hook
|
||||
add chain inet $ZAPRET_NFT_TABLE prenat
|
||||
flush chain inet $ZAPRET_NFT_TABLE prenat
|
||||
|
||||
add chain inet $ZAPRET_NFT_TABLE predefrag { type filter hook output priority -401; }
|
||||
flush chain inet $ZAPRET_NFT_TABLE predefrag
|
||||
add chain inet $ZAPRET_NFT_TABLE predefrag_nfqws
|
||||
flush chain inet $ZAPRET_NFT_TABLE predefrag_nfqws
|
||||
add rule inet $ZAPRET_NFT_TABLE predefrag mark and $DESYNC_MARK !=0 jump predefrag_nfqws comment "nfqws generated : avoid drop by INVALID conntrack state"
|
||||
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws mark and $DESYNC_MARK_POSTNAT !=0 notrack comment "postnat traffic"
|
||||
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws ip frag-off & 0x1fff != 0 notrack comment "ipfrag"
|
||||
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws exthdr frag exists notrack comment "ipfrag"
|
||||
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws tcp flags ! syn,rst,ack notrack comment "datanoack"
|
||||
|
||||
add set inet $ZAPRET_NFT_TABLE wanif { type ifname; }
|
||||
add set inet $ZAPRET_NFT_TABLE wanif6 { type ifname; }
|
||||
|
||||
add chain inet $ZAPRET_NFT_TABLE ruletest
|
||||
flush chain inet $ZAPRET_NFT_TABLE ruletest
|
||||
EOF
|
||||
[ -n "$POSTNAT_ALL" ] && {
|
||||
nft_flush_chain predefrag_nfqws
|
||||
nft_add_rule predefrag_nfqws notrack comment \"do not track nfqws generated packets to avoid nat tampering and defragmentation\"
|
||||
}
|
||||
[ "$FILTER_TTL_EXPIRED_ICMP" = 1 ] && {
|
||||
if is_postnat; then
|
||||
# can be caused by untracked nfqws-generated packets
|
||||
nft_add_rule prerouting_hook icmp type time-exceeded ct state invalid drop
|
||||
else
|
||||
nft_add_rule postrouting_hook mark and $DESYNC_MARK != 0 ct mark set ct mark or $DESYNC_MARK comment \"nfqws related : prevent ttl expired socket errors\"
|
||||
fi
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
nft_add_rule prerouting_hook icmp type time-exceeded ct mark and $DESYNC_MARK != 0 drop comment \"nfqws related : prevent ttl expired socket errors\"
|
||||
}
|
||||
[ "$DISABLE_IPV6" = "1" ] || {
|
||||
nft_add_rule prerouting_hook icmpv6 type time-exceeded ct mark and $DESYNC_MARK != 0 drop comment \"nfqws related : prevent ttl expired socket errors\"
|
||||
}
|
||||
}
|
||||
}
|
||||
nft_del_chains()
|
||||
{
|
||||
# do not delete all chains because of additional user hooks
|
||||
# they must be inside zapret table to use nfsets
|
||||
|
||||
cat << EOF | nft -f - 2>/dev/null
|
||||
delete chain inet $ZAPRET_NFT_TABLE postrouting_hook
|
||||
delete chain inet $ZAPRET_NFT_TABLE postnat_hook
|
||||
delete chain inet $ZAPRET_NFT_TABLE prerouting_hook
|
||||
delete chain inet $ZAPRET_NFT_TABLE prenat_hook
|
||||
delete chain inet $ZAPRET_NFT_TABLE forward_hook
|
||||
delete chain inet $ZAPRET_NFT_TABLE postrouting
|
||||
delete chain inet $ZAPRET_NFT_TABLE postnat
|
||||
delete chain inet $ZAPRET_NFT_TABLE prerouting
|
||||
delete chain inet $ZAPRET_NFT_TABLE prenat
|
||||
delete chain inet $ZAPRET_NFT_TABLE predefrag
|
||||
delete chain inet $ZAPRET_NFT_TABLE predefrag_nfqws
|
||||
delete chain inet $ZAPRET_NFT_TABLE flow_offload
|
||||
delete chain inet $ZAPRET_NFT_TABLE flow_offload_zapret
|
||||
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()
|
||||
{
|
||||
nft delete flowtable inet $ZAPRET_NFT_TABLE ft 2>/dev/null
|
||||
}
|
||||
nft_create_or_update_flowtable()
|
||||
{
|
||||
# $1 = flags ('offload' for hw offload)
|
||||
# $2,$3,$4,... - interfaces
|
||||
# can be called multiple times to add interfaces. interfaces can only be added , not removed
|
||||
local flags=$1 devices makelist
|
||||
shift
|
||||
# warning ! nft versions at least up to 1.0.1 do not allow interface names starting with digit in flowtable and do not allow quoting
|
||||
# warning ! openwrt fixes this in post-21.x snapshots with special nft patch
|
||||
# warning ! in traditional linux distros nft is unpatched and will fail with quoted interface definitions if unfixed
|
||||
[ -n "$flags" ] && flags="flags $flags;"
|
||||
for makelist in make_quoted_comma_list make_comma_list; do
|
||||
$makelist devices "$@"
|
||||
[ -n "$devices" ] && devices="devices={$devices};"
|
||||
nft add flowtable inet $ZAPRET_NFT_TABLE ft "{ hook ingress priority -1; $flags $devices }" && break
|
||||
done
|
||||
}
|
||||
nft_flush_ifsets()
|
||||
{
|
||||
cat << EOF | nft -f - 2>/dev/null
|
||||
flush set inet $ZAPRET_NFT_TABLE wanif
|
||||
flush set inet $ZAPRET_NFT_TABLE wanif6
|
||||
EOF
|
||||
}
|
||||
nft_list_ifsets()
|
||||
{
|
||||
nft list set inet $ZAPRET_NFT_TABLE wanif
|
||||
nft list set inet $ZAPRET_NFT_TABLE wanif6
|
||||
nft list flowtable inet $ZAPRET_NFT_TABLE ft 2>/dev/null
|
||||
}
|
||||
|
||||
nft_create_firewall()
|
||||
{
|
||||
nft_create_table
|
||||
nft_del_flowtable
|
||||
nft_create_chains
|
||||
}
|
||||
nft_del_firewall()
|
||||
{
|
||||
nft_del_chains
|
||||
nft_del_flowtable
|
||||
# leave ifsets and ipsets because they may be used by custom rules
|
||||
}
|
||||
|
||||
nft_add_rule()
|
||||
{
|
||||
# $1 - chain
|
||||
# $2,$3,... - rule(s)
|
||||
local chain="$1"
|
||||
shift
|
||||
nft add rule inet $ZAPRET_NFT_TABLE $chain $FW_EXTRA_PRE "$@"
|
||||
}
|
||||
nft_insert_rule()
|
||||
{
|
||||
# $1 - chain
|
||||
# $2,$3,... - rule(s)
|
||||
local chain="$1"
|
||||
shift
|
||||
nft insert rule inet $ZAPRET_NFT_TABLE $chain $FW_EXTRA_PRE "$@"
|
||||
}
|
||||
nft_add_set_element()
|
||||
{
|
||||
# $1 - set or map name
|
||||
# $2 - element
|
||||
[ -z "$2" ] || nft add element inet $ZAPRET_NFT_TABLE $1 "{ $2 }"
|
||||
}
|
||||
nft_add_set_elements()
|
||||
{
|
||||
# $1 - set or map name
|
||||
# $2,$3,... - element(s)
|
||||
local set="$1" elements
|
||||
shift
|
||||
make_comma_list elements "$@"
|
||||
nft_add_set_element $set "$elements"
|
||||
}
|
||||
nft_reverse_nfqws_rule()
|
||||
{
|
||||
echo "$@" | sed -e 's/oifname /iifname /g' -e 's/dport /sport /g' -e 's/daddr /saddr /g' -e 's/ct original /ct reply /g' -e "s/mark and $DESYNC_MARK == 0//g"
|
||||
}
|
||||
nft_add_nfqws_flow_exempt_rule()
|
||||
{
|
||||
# $1 - rule (must be all filters in one var)
|
||||
local FW_EXTRA_POST= FW_EXTRA_PRE=
|
||||
[ "$FLOWOFFLOAD" = 'software' -o "$FLOWOFFLOAD" = 'hardware' ] && \
|
||||
nft_insert_rule flow_offload_zapret "$1" return comment \"direct flow offloading exemption\"
|
||||
}
|
||||
|
||||
nft_apply_flow_offloading()
|
||||
{
|
||||
# ft can be absent
|
||||
nft_add_rule flow_offload_always flow add @ft 2>/dev/null && {
|
||||
nft_add_rule flow_offload_always counter comment \"if offload works here must not be too much traffic\"
|
||||
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
# allow only outgoing packets to initiate flow offload
|
||||
nft_add_rule forward_hook meta l4proto "{ tcp, udp }" oifname @wanif jump flow_offload
|
||||
nft_add_rule flow_offload ip daddr == @nozapret goto flow_offload_always
|
||||
}
|
||||
[ "$DISABLE_IPV6" = "1" ] || {
|
||||
nft_add_rule forward_hook meta l4proto "{ tcp, udp }" oifname @wanif6 jump flow_offload
|
||||
nft_add_rule flow_offload ip6 daddr == @nozapret6 goto flow_offload_always
|
||||
}
|
||||
nft_add_rule flow_offload jump flow_offload_zapret
|
||||
|
||||
nft_add_rule flow_offload_zapret goto flow_offload_always
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
nft_filter_apply_ipset_target4()
|
||||
{
|
||||
# $1 - var name of ipv4 nftables filter
|
||||
if [ "$MODE_FILTER" = "ipset" ]; then
|
||||
eval $1="\"\$$1 ip daddr @zapret\""
|
||||
fi
|
||||
}
|
||||
nft_filter_apply_ipset_target6()
|
||||
{
|
||||
# $1 - var name of ipv6 nftables filter
|
||||
if [ "$MODE_FILTER" = "ipset" ]; then
|
||||
eval $1="\"\$$1 ip6 daddr @zapret6\""
|
||||
fi
|
||||
}
|
||||
nft_filter_apply_ipset_target()
|
||||
{
|
||||
# $1 - var name of ipv4 nftables filter
|
||||
# $2 - var name of ipv6 nftables filter
|
||||
nft_filter_apply_ipset_target4 $1
|
||||
nft_filter_apply_ipset_target6 $2
|
||||
}
|
||||
|
||||
nft_mark_filter()
|
||||
{
|
||||
[ -n "$FILTER_MARK" ] && echo "mark and $FILTER_MARK != 0"
|
||||
}
|
||||
|
||||
nft_script_add_ifset_element()
|
||||
{
|
||||
# $1 - set name
|
||||
# $2 - space separated elements
|
||||
local elements
|
||||
[ -n "$2" ] && {
|
||||
make_quoted_comma_list elements $2
|
||||
script="${script}
|
||||
add element inet $ZAPRET_NFT_TABLE $1 { $elements }"
|
||||
}
|
||||
}
|
||||
nft_fill_ifsets()
|
||||
{
|
||||
# $1 - space separated lan interface names
|
||||
# $2 - space separated wan interface names
|
||||
# $3 - space separated wan6 interface names
|
||||
# 4,5,6 is needed for pppoe+openwrt case. looks like it's not easily possible to resolve ethernet device behind a pppoe interface
|
||||
# $4 - space separated lan physical interface names (optional)
|
||||
# $5 - space separated wan physical interface names (optional)
|
||||
# $6 - space separated wan6 physical interface names (optional)
|
||||
|
||||
local script i j ALLDEVS devs b
|
||||
|
||||
# if large sets exist nft works very ineffectively
|
||||
# looks like it analyzes the whole table blob to find required data pieces
|
||||
# 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"
|
||||
|
||||
[ "$DISABLE_IPV4" = "1" ] || nft_script_add_ifset_element wanif "$2"
|
||||
[ "$DISABLE_IPV6" = "1" ] || nft_script_add_ifset_element wanif6 "$3"
|
||||
|
||||
echo "$script" | nft -f -
|
||||
|
||||
case "$FLOWOFFLOAD" in
|
||||
software)
|
||||
ALLDEVS=$(unique $1 $2 $3)
|
||||
# unbound flowtable may cause error in older nft version
|
||||
nft_create_or_update_flowtable '' $ALLDEVS 2>/dev/null
|
||||
;;
|
||||
hardware)
|
||||
ALLDEVS=$(unique $1 $2 $3 $4 $5 $6)
|
||||
# first create unbound flowtable. may cause error in older nft version
|
||||
nft_create_or_update_flowtable 'offload' 2>/dev/null
|
||||
# then add elements. some of them can cause error because unsupported
|
||||
for i in $ALLDEVS; do
|
||||
# bridge members must be added instead of the bridge itself
|
||||
# some members may not support hw offload. example : lan1 lan2 lan3 support, wlan0 wlan1 - not
|
||||
b=
|
||||
devs=$(resolve_lower_devices $i)
|
||||
for j in $devs; do
|
||||
# do not display error if addition failed
|
||||
nft_create_or_update_flowtable 'offload' $j && b=1 2>/dev/null
|
||||
done
|
||||
[ -n "$b" ] || {
|
||||
# no lower devices added ? try to add interface itself
|
||||
nft_create_or_update_flowtable 'offload' $i 2>/dev/null
|
||||
}
|
||||
done
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
nft_only()
|
||||
{
|
||||
linux_fwtype
|
||||
|
||||
case "$FWTYPE" in
|
||||
nftables)
|
||||
"$@"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
nft_print_op()
|
||||
{
|
||||
echo "Inserting nftables ipv$3 rule for $2 : $1"
|
||||
}
|
||||
is_postnat()
|
||||
{
|
||||
[ "$POSTNAT" != 0 -o "$POSTNAT_ALL" = 1 ]
|
||||
}
|
||||
get_postchain()
|
||||
{
|
||||
if is_postnat ; then
|
||||
echo -n postnat
|
||||
else
|
||||
echo -n postrouting
|
||||
fi
|
||||
}
|
||||
get_prechain()
|
||||
{
|
||||
if is_postnat ; then
|
||||
echo -n prenat
|
||||
else
|
||||
echo -n prerouting
|
||||
fi
|
||||
}
|
||||
_nft_fw_nfqws_post4()
|
||||
{
|
||||
# $1 - filter ipv4
|
||||
# $2 - queue number
|
||||
# $3 - not-empty if wan interface filtering required
|
||||
|
||||
[ "$DISABLE_IPV4" = "1" -o -z "$1" ] || {
|
||||
local filter="$1" port="$2" rule chain=$(get_postchain) setmark
|
||||
nft_print_op "$filter" "nfqws postrouting (qnum $port)" 4
|
||||
rule="meta nfproto ipv4 $filter"
|
||||
is_postnat && setmark="meta mark set meta mark or $DESYNC_MARK_POSTNAT"
|
||||
nft_insert_rule $chain $rule $setmark $CONNMARKER $FW_EXTRA_POST queue num $port bypass
|
||||
nft_add_nfqws_flow_exempt_rule "$rule"
|
||||
nft_activate_chain4 $chain daddr
|
||||
}
|
||||
}
|
||||
_nft_fw_nfqws_post6()
|
||||
{
|
||||
# $1 - filter ipv6
|
||||
# $2 - queue number
|
||||
# $3 - not-empty if wan interface filtering required
|
||||
|
||||
[ "$DISABLE_IPV6" = "1" -o -z "$1" ] || {
|
||||
local filter="$1" port="$2" rule chain=$(get_postchain) setmark
|
||||
nft_print_op "$filter" "nfqws postrouting (qnum $port)" 6
|
||||
rule="meta nfproto ipv6 $filter"
|
||||
is_postnat && setmark="meta mark set meta mark or $DESYNC_MARK_POSTNAT"
|
||||
nft_insert_rule $chain $rule $setmark $CONNMARKER $FW_EXTRA_POST queue num $port bypass
|
||||
nft_add_nfqws_flow_exempt_rule "$rule"
|
||||
nft_activate_chain6 $chain daddr
|
||||
}
|
||||
}
|
||||
nft_fw_nfqws_post()
|
||||
{
|
||||
# $1 - filter ipv4
|
||||
# $2 - filter ipv6
|
||||
# $3 - queue number
|
||||
|
||||
nft_fw_nfqws_post4 "$1" $3
|
||||
nft_fw_nfqws_post6 "$2" $3
|
||||
}
|
||||
|
||||
_nft_fw_nfqws_pre4()
|
||||
{
|
||||
# $1 - filter ipv4
|
||||
# $2 - queue number
|
||||
# $3 - not-empty if wan interface filtering required
|
||||
|
||||
[ "$DISABLE_IPV4" = "1" -o -z "$1" ] || {
|
||||
local filter="$1" port="$2" rule chain=$(get_prechain)
|
||||
nft_print_op "$filter" "nfqws prerouting (qnum $port)" 4
|
||||
rule="meta nfproto ipv4 $filter"
|
||||
nft_insert_rule $chain $rule $CONNMARKER $FW_EXTRA_POST queue num $port bypass
|
||||
nft_activate_chain4 $chain saddr
|
||||
}
|
||||
}
|
||||
_nft_fw_nfqws_pre6()
|
||||
{
|
||||
# $1 - filter ipv6
|
||||
# $2 - queue number
|
||||
# $3 - not-empty if wan interface filtering required
|
||||
|
||||
[ "$DISABLE_IPV6" = "1" -o -z "$1" ] || {
|
||||
local filter="$1" port="$2" rule chain=$(get_prechain)
|
||||
nft_print_op "$filter" "nfqws prerouting (qnum $port)" 6
|
||||
rule="meta nfproto ipv6 $filter"
|
||||
nft_insert_rule $chain $rule $CONNMARKER $FW_EXTRA_POST queue num $port bypass
|
||||
nft_activate_chain6 $chain saddr
|
||||
}
|
||||
}
|
||||
nft_fw_nfqws_pre()
|
||||
{
|
||||
# $1 - filter ipv4
|
||||
# $2 - filter ipv6
|
||||
# $3 - queue number
|
||||
|
||||
nft_fw_nfqws_pre4 "$1" $3
|
||||
nft_fw_nfqws_pre6 "$2" $3
|
||||
}
|
||||
|
||||
nft_fw_nfqws_both4()
|
||||
{
|
||||
# $1 - filter ipv4
|
||||
# $2 - queue number
|
||||
nft_fw_nfqws_post4 "$@"
|
||||
nft_fw_nfqws_pre4 "$(nft_reverse_nfqws_rule $1)" $2
|
||||
}
|
||||
nft_fw_nfqws_both6()
|
||||
{
|
||||
# $1 - filter ipv6
|
||||
# $2 - queue number
|
||||
nft_fw_nfqws_post6 "$@"
|
||||
nft_fw_nfqws_pre6 "$(nft_reverse_nfqws_rule $1)" $2
|
||||
}
|
||||
nft_fw_nfqws_both()
|
||||
{
|
||||
# $1 - filter ipv4
|
||||
# $2 - filter ipv6
|
||||
# $3 - queue number
|
||||
nft_fw_nfqws_both4 "$1" "$3"
|
||||
nft_fw_nfqws_both6 "$2" "$3"
|
||||
}
|
||||
|
||||
zapret_reload_ifsets()
|
||||
{
|
||||
nft_only nft_create_table ; nft_fill_ifsets_overload
|
||||
return 0
|
||||
}
|
||||
zapret_list_ifsets()
|
||||
{
|
||||
nft_only nft_list_ifsets
|
||||
return 0
|
||||
}
|
||||
zapret_list_table()
|
||||
{
|
||||
nft_only nft_list_table
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
|
||||
nft_fw_reverse_nfqws_rule4()
|
||||
{
|
||||
nft_fw_nfqws_pre4 "$(nft_reverse_nfqws_rule "$1")" $2
|
||||
}
|
||||
nft_fw_reverse_nfqws_rule6()
|
||||
{
|
||||
nft_fw_nfqws_pre6 "$(nft_reverse_nfqws_rule "$1")" $2
|
||||
}
|
||||
nft_fw_reverse_nfqws_rule()
|
||||
{
|
||||
# ensure that modes relying on incoming traffic work
|
||||
# $1 - rule4
|
||||
# $2 - rule6
|
||||
# $3 - queue number
|
||||
nft_fw_reverse_nfqws_rule4 "$1" $3
|
||||
nft_fw_reverse_nfqws_rule6 "$2" $3
|
||||
}
|
||||
|
||||
nft_first_packets()
|
||||
{
|
||||
# $1 - packet count
|
||||
[ -n "$1" -a "$1" != keepalive ] && [ "$1" -ge 1 ] &&
|
||||
{
|
||||
if [ "$1" = 1 ] ; then
|
||||
echo "$nft_connbytes 1"
|
||||
else
|
||||
echo "$nft_connbytes 1-$1"
|
||||
fi
|
||||
}
|
||||
}
|
||||
|
||||
nft_apply_nfqws_in_out()
|
||||
{
|
||||
# $1 - tcp,udp
|
||||
# $2 - ports
|
||||
# $3 - PKT_OUT. special value : 'keepalive'
|
||||
# $4 - PKT_IN
|
||||
local f4 f6 first_packets_only
|
||||
[ -n "$2" ] || return
|
||||
[ -n "$3" -a "$3" != 0 ] &&
|
||||
{
|
||||
first_packets_only="$(nft_first_packets $3)"
|
||||
f4="$1 dport {$2} $first_packets_only"
|
||||
f6=$f4
|
||||
nft_filter_apply_ipset_target f4 f6
|
||||
nft_fw_nfqws_post "$f4" "$f6" $QNUM
|
||||
}
|
||||
[ -n "$4" -a "$4" != 0 ] &&
|
||||
{
|
||||
first_packets_only="$(nft_first_packets $4)"
|
||||
f4="$1 dport {$2} $first_packets_only"
|
||||
f6=$f4
|
||||
nft_filter_apply_ipset_target f4 f6
|
||||
nft_fw_reverse_nfqws_rule "$f4" "$f6" $QNUM
|
||||
}
|
||||
}
|
||||
|
||||
zapret_apply_firewall_standard_nfqws_rules_nft()
|
||||
{
|
||||
[ "$NFQWS2_ENABLE" = 1 ] && {
|
||||
nft_apply_nfqws_in_out tcp "$NFQWS2_PORTS_TCP" "$NFQWS2_TCP_PKT_OUT" "$NFQWS2_TCP_PKT_IN"
|
||||
nft_apply_nfqws_in_out tcp "$NFQWS2_PORTS_TCP_KEEPALIVE" keepalive "$NFQWS2_TCP_PKT_IN"
|
||||
nft_apply_nfqws_in_out udp "$NFQWS2_PORTS_UDP" "$NFQWS2_UDP_PKT_OUT" "$NFQWS2_UDP_PKT_IN"
|
||||
nft_apply_nfqws_in_out udp "$NFQWS2_PORTS_UDP_KEEPALIVE" keepalive "$NFQWS2_UDP_PKT_IN"
|
||||
}
|
||||
}
|
||||
zapret_apply_firewall_standard_rules_nft()
|
||||
{
|
||||
zapret_apply_firewall_standard_nfqws_rules_nft
|
||||
}
|
||||
|
||||
zapret_apply_firewall_rules_nft()
|
||||
{
|
||||
zapret_apply_firewall_standard_rules_nft
|
||||
custom_runner zapret_custom_firewall_nft
|
||||
}
|
||||
|
||||
zapret_apply_firewall_nft()
|
||||
{
|
||||
echo Applying nftables
|
||||
|
||||
create_ipset no-update
|
||||
nft_create_firewall
|
||||
nft_fill_ifsets_overload
|
||||
|
||||
zapret_apply_firewall_rules_nft
|
||||
|
||||
[ "$FLOWOFFLOAD" = 'software' -o "$FLOWOFFLOAD" = 'hardware' ] && nft_apply_flow_offloading
|
||||
|
||||
return 0
|
||||
}
|
||||
zapret_unapply_firewall_nft()
|
||||
{
|
||||
echo Clearing nftables
|
||||
|
||||
nft_del_firewall
|
||||
custom_runner zapret_custom_firewall_nft_flush
|
||||
return 0
|
||||
}
|
||||
zapret_do_firewall_nft()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
|
||||
if [ "$1" = 0 ] ; then
|
||||
zapret_unapply_firewall_nft
|
||||
else
|
||||
zapret_apply_firewall_nft
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# ctmark is not available in POSTNAT mode
|
||||
CONNMARKER=
|
||||
[ "$FILTER_TTL_EXPIRED_ICMP" = 1 ] && is_postnat && CONNMARKER="ct mark set ct mark or $DESYNC_MARK"
|
||||
@@ -2,7 +2,7 @@
|
||||
# change values here
|
||||
|
||||
# can help in case /tmp has not enough space
|
||||
#TMPDIR=/opt/zapret/tmp
|
||||
#TMPDIR=/opt/zapret2/tmp
|
||||
|
||||
# redefine user for zapret daemons. required on Keenetic
|
||||
#WS_USER=nobody
|
||||
@@ -20,15 +20,22 @@ SET_MAXELEM=522288
|
||||
# too large hashsize will waste lots of RAM
|
||||
IPSET_OPT="hashsize 262144 maxelem $SET_MAXELEM"
|
||||
# dynamically generate additional ip. $1 = ipset/nfset/table name
|
||||
#IPSET_HOOK="/etc/zapret.ipset.hook"
|
||||
#IPSET_HOOK="/etc/zapret2.ipset.hook"
|
||||
|
||||
# options for ip2net. "-4" or "-6" auto added by ipset create script
|
||||
IP2NET_OPT4="--prefix-length=22-30 --v4-threshold=3/4"
|
||||
IP2NET_OPT6="--prefix-length=56-64 --v6-threshold=5"
|
||||
# options for auto hostlist
|
||||
# NOTE : in order for these adjustment to work it's required to redirect enough starting packets
|
||||
# NOTE : set PKT_IN, PKT_OUT variables appropriately
|
||||
AUTOHOSTLIST_INCOMING_MAXSEQ=4096
|
||||
AUTOHOSTLIST_RETRANS_MAXSEQ=32768
|
||||
AUTOHOSTLIST_RETRANS_RESET=1
|
||||
AUTOHOSTLIST_RETRANS_THRESHOLD=3
|
||||
AUTOHOSTLIST_FAIL_THRESHOLD=3
|
||||
AUTOHOSTLIST_FAIL_TIME=60
|
||||
AUTOHOSTLIST_UDP_IN=1
|
||||
AUTOHOSTLIST_UDP_OUT=4
|
||||
# 1 = debug autohostlist positives to ipset/zapret-hosts-auto-debug.log
|
||||
AUTOHOSTLIST_DEBUGLOG=0
|
||||
|
||||
@@ -60,11 +67,10 @@ NFQWS2_PORTS_TCP=80,443
|
||||
NFQWS2_PORTS_UDP=443
|
||||
# PKT_OUT means connbytes dir original
|
||||
# PKT_IN means connbytes dir reply
|
||||
# this is --dpi-desync-cutoff=nX kernel mode implementation for linux. it saves a lot of CPU.
|
||||
NFQWS2_TCP_PKT_OUT=$((6+$AUTOHOSTLIST_RETRANS_THRESHOLD))
|
||||
NFQWS2_TCP_PKT_IN=3
|
||||
NFQWS2_UDP_PKT_OUT=$((6+$AUTOHOSTLIST_RETRANS_THRESHOLD))
|
||||
NFQWS2_UDP_PKT_IN=0
|
||||
NFQWS2_TCP_PKT_OUT=20
|
||||
NFQWS2_TCP_PKT_IN=10
|
||||
NFQWS2_UDP_PKT_OUT=5
|
||||
NFQWS2_UDP_PKT_IN=3
|
||||
# redirect outgoing traffic without connbytes limiter and incoming with connbytes limiter
|
||||
# normally it's needed only for stateless DPI that matches every packet in a single TCP session
|
||||
# typical example are plain HTTP keep alives
|
||||
@@ -75,9 +81,9 @@ NFQWS2_UDP_PKT_IN=0
|
||||
# hostlist markers are replaced to empty string if MODE_FILTER does not satisfy
|
||||
# <HOSTLIST_NOAUTO> appends ipset/zapret-hosts-auto.txt as normal list
|
||||
NFQWS2_OPT="
|
||||
--filter-tcp=80 --payload=http_req --lua-desync=fake:blob=fake_default_http:tcp_md5 --lua-desync=multisplit:pos=method+2 <HOSTLIST> --new
|
||||
--filter-tcp=443 --payload=tls_client_hello --lua-desync=fake:blob=fake_default_tls:tcp_md5:tcp_seq=-10000 --lua-desync=multidisorder:pos=1,midsld <HOSTLIST> --new
|
||||
--filter-udp=443 --payload=quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=6 <HOSTLIST_NOAUTO> --new
|
||||
--filter-tcp=80 --filter-l7=http <HOSTLIST> --payload=http_req --lua-desync=fake:blob=fake_default_http:tcp_md5 --lua-desync=multisplit:pos=method+2 --new
|
||||
--filter-tcp=443 --filter-l7=tls <HOSTLIST> --payload=tls_client_hello --lua-desync=fake:blob=fake_default_tls:tcp_md5:tcp_seq=-10000 --lua-desync=multidisorder:pos=1,midsld --new
|
||||
--filter-udp=443 --filter-l7=quic <HOSTLIST_NOAUTO> --payload=quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=6
|
||||
"
|
||||
|
||||
# none,ipset,hostlist,autohostlist
|
||||
@@ -86,15 +92,18 @@ MODE_FILTER=none
|
||||
# donttouch,none,software,hardware
|
||||
FLOWOFFLOAD=donttouch
|
||||
|
||||
# openwrt: specify networks to be treated as LAN. default is "lan"
|
||||
#OPENWRT_LAN="lan lan2 lan3"
|
||||
# openwrt: specify networks to be treated as WAN. default wans are interfaces with default route
|
||||
#OPENWRT_WAN4="wan vpn"
|
||||
#OPENWRT_WAN6="wan6 vpn6"
|
||||
|
||||
# for routers based on desktop linux and macos. has no effect in openwrt.
|
||||
# optionally CHOOSE WAN/WAN6 NETWORK INTERFACES
|
||||
# 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"
|
||||
|
||||
@@ -102,10 +111,10 @@ FLOWOFFLOAD=donttouch
|
||||
# not applicable to openwrt with firewall3+iptables
|
||||
INIT_APPLY_FW=1
|
||||
# firewall apply hooks
|
||||
#INIT_FW_PRE_UP_HOOK="/etc/firewall.zapret.hook.pre_up"
|
||||
#INIT_FW_POST_UP_HOOK="/etc/firewall.zapret.hook.post_up"
|
||||
#INIT_FW_PRE_DOWN_HOOK="/etc/firewall.zapret.hook.pre_down"
|
||||
#INIT_FW_POST_DOWN_HOOK="/etc/firewall.zapret.hook.post_down"
|
||||
#INIT_FW_PRE_UP_HOOK="/etc/firewall.zapret2.hook.pre_up"
|
||||
#INIT_FW_POST_UP_HOOK="/etc/firewall.zapret2.hook.post_up"
|
||||
#INIT_FW_PRE_DOWN_HOOK="/etc/firewall.zapret2.hook.pre_down"
|
||||
#INIT_FW_POST_DOWN_HOOK="/etc/firewall.zapret2.hook.post_down"
|
||||
|
||||
# do not work with ipv4
|
||||
#DISABLE_IPV4=1
|
||||
|
||||
110
docs/changes.txt
110
docs/changes.txt
@@ -34,3 +34,113 @@ v0.2
|
||||
* zapret-lib: bugfixes
|
||||
* zapret-lib: remove ip6_hopbyhop_x2 fooling, separately add second hopbyhop header using ip6_hopbyhop2
|
||||
* zapret-pcap
|
||||
|
||||
v0.3
|
||||
|
||||
* init.d launch scripts
|
||||
* init.d: 40-webserver custom script
|
||||
* install_easy
|
||||
|
||||
v0.4
|
||||
|
||||
* nfqws2: profile names and cookies
|
||||
* nfqws2: profile templates
|
||||
* nfqws2: remove stun_binding_req, replace to stun. no more message type details
|
||||
* nfqws2: proper conntack position for replayed packets
|
||||
* nfqws2: execution_plan, execution_plan_cancel
|
||||
* blockcheck2: fix broken dns cache
|
||||
* nfqws2: LUA_COMPAT_VER tracking
|
||||
|
||||
v0.5
|
||||
|
||||
* nfqws2: u8add,u16add,u24add,u32add luacalls
|
||||
* nfqws2: abandon any arithmetics beyond 32bit (because lua 5.1 does not support 64 bit integers, store everything as double)
|
||||
* nfqws2: fix issues with 32-bit lua_Integer in lua<5.3 on 32-bit platforms
|
||||
* nfqws2: instance_cutoff luacall just warns and do nothing if ctx is nil
|
||||
* actions: build nfqws2 x86 binary with LUA 5.4, not with luajit
|
||||
* zapret-lib: http_reply, url and nld dissectors
|
||||
* zapret-lib: instance_cutoff_shim
|
||||
* zapret-auto: circular orchestrator
|
||||
|
||||
v0.5.1
|
||||
|
||||
* zapret-auto: separate failure detection logic
|
||||
* blockcheck2: fix broken http3 test
|
||||
|
||||
v0.6
|
||||
|
||||
* zapret-lib,zapret-antidpi: tls_mod_shim supports sni=%var subst
|
||||
* blockcheck2: syndata tests
|
||||
* nfqws2: reasm support negative overlaps. gaps are not supported.
|
||||
* nfqws2,zapret-auto: changed retransmission detection scheme.
|
||||
* zapret-auto: udp_in/udp_out failure detection
|
||||
|
||||
v0.6.1
|
||||
|
||||
* zapret-lib, zapret-auto: condition and stopif orchestrators
|
||||
* zapret-lib: detect_payload_str - sample lua payload detector
|
||||
* blockcheck2: unterminated string fix
|
||||
|
||||
v0.7
|
||||
|
||||
* nfqws2, zapret-lib : fix non-working % and # arg substitution under orchestrator
|
||||
* nfqws2, zapret-lib : structure conntrack in/out positions. pass in desync.track.pos.{client,server,direct,reverse} position tables
|
||||
* nfqws2: autohostlist: trigger RST and http redirect failures only within specified relative sequence
|
||||
* nfqws2: autohostlist: trigger http redirect failure if payload is http_req without connection proto check
|
||||
* nfqws2: push desync.track.pos.dt as float with nsec accuracy
|
||||
* zapret-auto: override host autostate key in automate_host_record
|
||||
* nfqws2: rewrite udp autohostlist failure detector logic
|
||||
|
||||
v0.7.1
|
||||
|
||||
* init.d: nft fix non-working incoming redirect
|
||||
* nfqws2: cancel reasm if server window size is smaller than expected reasm size
|
||||
* nfqws2: add EOL at the end of truncated buffered DLOG line if it's too large. increase log line buffer
|
||||
* nfqws2: autohostlist reset fail counter if udp_in > threshold
|
||||
* nfqws2: reduced default retrans maxseq to 32768
|
||||
* nfqws2: solved inability to get SSID using nl80211 on kernels 5.19+
|
||||
|
||||
v0.7.2
|
||||
|
||||
* zapret-lib: fix broken is_retransmission()
|
||||
* zapret-auto: add success detector logic
|
||||
* nfqws2: clean lua cutoff on profile change
|
||||
* zapret-auto: separate hostkey function
|
||||
|
||||
v0.7.4
|
||||
|
||||
* nfqws2, zapret-lib : check tcp sequence range overflow
|
||||
* zapret-lib: seq compare functions
|
||||
* nfqws2: add l3_len, l4_len to dissect
|
||||
* nfqws2: fix broken l7proto profile rediscovery
|
||||
* winws2: harden sandbox. disable child process execution , some UI interaction and desktop settings change
|
||||
|
||||
v0.7.5
|
||||
|
||||
* zapret-auto: orchestrator "repeater"
|
||||
* blockcheck2: check http3 with ipv6 exthdr
|
||||
* github actions: separate target arm-old with LUA classic, not JIT
|
||||
* zapret-auto: iff/neg in repeater
|
||||
* zapret-antidpi: multidisorder_legacy
|
||||
* ipset: remove get_reestr_hostlist.sh and get_reestr_resolve.sh because zapret-info does not and will probably not ever update
|
||||
* nfqws2: fix "reasm cancelled" if no incoming traffic redirected
|
||||
* blockcheck2: MULTIDISORDER=multidisorder_legacy
|
||||
|
||||
v0.7.6
|
||||
|
||||
* nfqws2: reevaluate profile on l7/host discovery in any direction
|
||||
* nfqws2: dtls protocol detection
|
||||
* nfqws2: autohostlist reset retransmitter to break long wait
|
||||
* zapret-auto: stadard_failure_detector reset retransmitter to break long wait
|
||||
* nfqws2, init.d, windivert : dht and wg detection changes
|
||||
|
||||
v0.8.0
|
||||
|
||||
* init.d: 50-dht4all NFQWS_OPT_DHT_PKT_OUT
|
||||
* nfqws2: (LUA_COMPAT_VER=4) support 48-bit arithmetics
|
||||
* github actions: remove arm-old target - luajit fail reason revealed
|
||||
* nfqws2: do not treat quic handshake messages as initials
|
||||
* zapret-lib: tls dissector/reconstructor
|
||||
* zapret-antidpi: tls_client_hello_clone
|
||||
* zapret-antidpi: "optional" arg to blob taking functions
|
||||
* nfqws2: support gzipped lua file. auto use script.lua.gz
|
||||
|
||||
11
docs/changes_compat.txt
Normal file
11
docs/changes_compat.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
Here listed all api breaking changes.
|
||||
When something changes capable of breaking things NFQWS2_COMPAT_VER increases.
|
||||
|
||||
v2
|
||||
* removed "stun_binding_req" specialized payload. replaced with common "stun" - any stun packets, not only binding request.
|
||||
every LUA relying on desync.l7payload should be revised.
|
||||
nfqws2 --payload option and init.d custom scripts must be updated.
|
||||
|
||||
v3
|
||||
* restructured desync.track. pass positions in desync.track.pos.{client,server,direct,reverse}
|
||||
code relying on conntrack counters and sequence numbers must be rewritten
|
||||
@@ -24,8 +24,8 @@ define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/ip2net/install
|
||||
$(INSTALL_DIR) $(1)/opt/zapret/binaries/my
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ip2net $(1)/opt/zapret/binaries/my
|
||||
$(INSTALL_DIR) $(1)/opt/zapret2/binaries/my
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ip2net $(1)/opt/zapret2/binaries/my
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ip2net))
|
||||
|
||||
@@ -24,8 +24,8 @@ define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/mdig/install
|
||||
$(INSTALL_DIR) $(1)/opt/zapret/binaries/my
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/mdig $(1)/opt/zapret/binaries/my
|
||||
$(INSTALL_DIR) $(1)/opt/zapret2/binaries/my
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/mdig $(1)/opt/zapret2/binaries/my
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,mdig))
|
||||
|
||||
@@ -31,7 +31,7 @@ endef
|
||||
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)
|
||||
$(CP) ./nfq/* $(PKG_BUILD_DIR)/
|
||||
$(CP) ./nfq2/* $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
@@ -39,8 +39,8 @@ define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/nfqws2/install
|
||||
$(INSTALL_DIR) $(1)/opt/zapret/binaries/my
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/nfqws2 $(1)/opt/zapret/binaries/my
|
||||
$(INSTALL_DIR) $(1)/opt/zapret2/binaries/my
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/nfqws2 $(1)/opt/zapret2/binaries/my
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,nfqws2))
|
||||
|
||||
@@ -1 +1 @@
|
||||
Copy "nfq" folder here !
|
||||
Copy "nfq2" folder here !
|
||||
|
||||
5063
docs/manual.md
Normal file
5063
docs/manual.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,3 @@
|
||||
# zapret2 v0.2
|
||||
|
||||
## Зачем это нужно
|
||||
|
||||
Автономное средство противодействия DPI, которое не требует подключения каких-либо сторонних серверов. Может помочь
|
||||
@@ -10,6 +8,20 @@ VPN. Может использоваться для частичной проз
|
||||
традиционные Linux-системы, FreeBSD, OpenBSD, Windows. В некоторых случаях возможна самостоятельная прикрутка
|
||||
решения к различным прошивкам.
|
||||
|
||||
[Полный мануал](manual.md)
|
||||
|
||||
|
||||
## Поддержать разработчика
|
||||
|
||||
Если вы считаете проект полезным и желаете поддержать разработку, направляйте ваши пожертвования на следующие адреса криптокошельков :
|
||||
|
||||
USDT `0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E` (предпочительно сеть ERC-20)
|
||||
|
||||
BTC `bc1qhqew3mrvp47uk2vevt5sctp7p2x9m7m5kkchve`
|
||||
|
||||
ETH `0x3d52Ce15B7Be734c53fc9526ECbAB8267b63d66E`
|
||||
|
||||
|
||||
## Чем это отличается от zapret1
|
||||
|
||||
zapret2 является дальнейшим развитием проекта zapret.
|
||||
@@ -24,12 +36,12 @@ zapret2 является дальнейшим развитием проекта
|
||||
или хотя бы область , в которой их можно искать, плюс владеющий базовыми навыками программирования.
|
||||
|
||||
*nfqws2* оставляет в себе практически тот же функционал - распознавание протоколов, реассемблинг, дешифровка, управление профилями, хостлисты, ipset-ы, базовая фильтрация.
|
||||
Но он полностью лишается возможностей самостоятельно воздействовать на трафик. Часть "дурения" переносится в скриптовой язык программирования LUA.
|
||||
Но он полностью лишается возможностей самостоятельно воздействовать на трафик. Часть "дурения" переносится в скриптовой язык программирования Lua.
|
||||
|
||||
LUA код получает от C кода структурированное представление приходящих пакетов в виде дерева (диссекты), подобного тем, что вы видите в wireshark.
|
||||
Lua код получает от C кода структурированное представление приходящих пакетов в виде дерева (диссекты), подобного тем, что вы видите в wireshark.
|
||||
Туда же приходят результаты сборки или дешифровки частей некоторых протоколов (tls, quic).
|
||||
С код предоставляет функции-хелперы, позволяющие отсылать пакеты, работать с двоичными данными, разбирать TLS, искать маркер-позции и т.д.
|
||||
Имеется библиотека хелперов, написанных на LUA, а так же готовая библиотека программ атаки на DPI (стратегий), реализующая функции *nfqws1* в расширенном варианте
|
||||
Имеется библиотека хелперов, написанных на Lua, а так же готовая библиотека программ атаки на DPI (стратегий), реализующая функции *nfqws1* в расширенном варианте
|
||||
и с большей гибкостью.
|
||||
|
||||
Вы всегда сможете взять и дописать что-то свое. В этом и есть смысл, чтобы борьбой с DPI смог заняться любой, кто разбирается в пакетах.
|
||||
@@ -40,8 +52,8 @@ zapret2 - инструмент для таких энтузиастов. Но э
|
||||
|
||||
## С чего начать
|
||||
|
||||
Хотелось бы избежать "талмуда" на главной странице. Поэтому начнем со способа запуска *nfqws2* и описания способов портирования стратегий *nfqws1* - как в *nfqws2* сделать то же самое, что можно было в *nfqws1*.
|
||||
Когда вы поймете как это работает, вы можете посмотреть LUA код, находящийся "под капотом". Разобрать как он работает, попробовать написать что-то свое.
|
||||
Хотелось бы избежать [талмуда](manual.md) на главной странице. Поэтому начнем со способа запуска *nfqws2* и описания способов портирования стратегий *nfqws1* - как в *nfqws2* сделать то же самое, что можно было в *nfqws1*.
|
||||
Когда вы поймете как это работает, вы можете посмотреть Lua код, находящийся "под капотом". Разобрать как он работает, попробовать написать что-то свое.
|
||||
"талмуд" обязательно будет, как он есть у любых более-менее сложных проектов. Он нужен как справочник.
|
||||
|
||||
### Механика обработки трафика
|
||||
@@ -90,11 +102,11 @@ nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-antidpi.
|
||||
--payload=tls_client_hello,http_req --lua-desync=multisplit:pos=1:seqovl=5:seqovl_pattern=0x1603030000
|
||||
```
|
||||
|
||||
Данный пример предполагает, что в той же директории находятся файлы `zapret-lib.lua` - библиотека хелперов на LUA и `zapret-antidpi.lua` - библиотека базовых стратегий.
|
||||
`--lua-init` может содержать LUA код в виде строки. Так удобно писать простой код, например присвоить константу переменной, чтобы не создавать файлы ради этой мелочи.
|
||||
Данный пример предполагает, что в той же директории находятся файлы `zapret-lib.lua` - библиотека хелперов на Lua и `zapret-antidpi.lua` - библиотека базовых стратегий.
|
||||
`--lua-init` может содержать Lua код в виде строки. Так удобно писать простой код, например присвоить константу переменной, чтобы не создавать файлы ради этой мелочи.
|
||||
Либо подцепляется файл, если значение параметра начинается с `@`. Код из `--lua-init` выполняется 1 раз при старте.
|
||||
|
||||
Далее указаны параметры `--lua-desync`. Они содержат имя LUA функции, вызываемой при обработке каждого пакета, проходящего через профиль мультистратегии.
|
||||
Далее указаны параметры `--lua-desync`. Они содержат имя Lua функции, вызываемой при обработке каждого пакета, проходящего через профиль мультистратегии.
|
||||
После двоеточия и через двоеточия следуют параметры для данной функции в формате `param[=value]`. В примере реализована стратегия
|
||||
|
||||
```
|
||||
@@ -110,7 +122,7 @@ nfqws --qnum 200 --debug \
|
||||
Тип пейлоада - тип данных, содержащихся в пакете или группе пакетов. Например, протокол соединения может быть tls, а пейлоады - tls_client_hello, tls_server_hello, unknown.
|
||||
|
||||
Другое важное отличие - отсутствие жестко определенных фаз десинхронизации. То, что вы раньше писали как `fake,multisplit` реализуется двумя
|
||||
последовательно вызываемыми LUA функциями. Их может быть столько, сколько нужно, учитывая логику прохождения пакетов и операций с ними, и у каждой могут быть свои параметры.
|
||||
последовательно вызываемыми Lua функциями. Их может быть столько, сколько нужно, учитывая логику прохождения пакетов и операций с ними, и у каждой могут быть свои параметры.
|
||||
Может даже несколько раз вызываться одна и так же функция с разными параметрами. Так, например, можно послать несколько фейков, причем с разными фулингами.
|
||||
Конкретный вызов `--lua-desync` функции называется инстансом. Инстанс - это связка имени функции, номера вызова внутри профиля и номера самого профиля.
|
||||
Это похоже на одну программу, которую можно запустить много раз с разными параметрами.
|
||||
@@ -118,11 +130,11 @@ nfqws --qnum 200 --debug \
|
||||
Другое немаловажное отличие - поддержка автоматической tcp сегментации средствами `zapret-lib.lua`. Вам больше не нужно думать о размерах отсылаемых tcp пакетов.
|
||||
По каждому соединению отслеживается MSS. Если пакет не влезает в MSS, выполняется сегментация.
|
||||
Например, это может случиться при отправке tls фейка с kyber. Или если вы режете kyber tls так, что одна из частей получается размером 1600 байт,
|
||||
что, очевидно, не влезает в MTU. Или если вы задали seqovl=10000. В *nfqws1* такое значение вызвало бы ошибку. Функция LUA `rawsend_dissect_segmented` отправит
|
||||
что, очевидно, не влезает в MTU. Или если вы задали seqovl=10000. В *nfqws1* такое значение вызвало бы ошибку. Функция Lua `rawsend_dissect_segmented` отправит
|
||||
несколько tcp сегментов с начальным sequence -10000 общим размером 10000 байт, в последнем из которых будет кусок оригинального сообщения.
|
||||
|
||||
В *nfqws2* нет жестко зашитых параметров кастомных фейков типа `--dpi-desync-fake-tls`, `dpi-desync-fake-http` и тд.
|
||||
Вместо них есть блобы. Блоб (blob) - это переменная LUA типа *string*, содержащая блок двоичных данных произвольной длины. От 1 байта до гигабайтов.
|
||||
Вместо них есть блобы. Блоб (blob) - это переменная Lua типа *string*, содержащая блок двоичных данных произвольной длины. От 1 байта до гигабайтов.
|
||||
*nfqws2* автоматически инициализирует блобы со стандартными фейками tls, http, quic, как это и было в *nfqws1*.
|
||||
Блобы могут быть заданы как hex-строка прямо в параметре desync функции, либо пред-загружены при старте с помощью параметра `--blob=name:0xHEX|[+ofs]@filename`
|
||||
|
||||
@@ -155,15 +167,15 @@ range задается как `mX-mY`, `mX<mY`, `-mY`, `<mY`, `mX-`.
|
||||
Следующий профиль снова принимает значения по умолчанию.
|
||||
|
||||
Что будет, если вы не напишите фильтр `--payload` для fake или multisplit ? В *nfqws1* без `--dpi-desync-any-protocol` они работали только по известным пейлоадам.
|
||||
В *nfqws2* "any protocol" - режим по умолчанию. Однако, функции из библиотеки `zapret-antidpi.lua` написаны так, что по умолчанию работают только по известные пейлоадам
|
||||
В *nfqws2* "any protocol" - режим по умолчанию. Однако, функции из библиотеки `zapret-antidpi.lua` написаны так, что по умолчанию работают только по известным пейлоадам
|
||||
и не работают по пустым пакетам или unknown - точно так же, как это было в *nfqws1*.
|
||||
Но лучше все-же писать фильтры `--payload`, потому что они работают на уровне C кода, который выполняется существенно быстрее, чем LUA.
|
||||
Но лучше все-же писать фильтры `--payload`, потому что они работают на уровне C кода, который выполняется существенно быстрее, чем Lua.
|
||||
|
||||
Диссект пакета проходит поочередно по всем `--lua-desync` инстансам профиля, для которых не выполняется условие отсечения (cutoff).
|
||||
Отсечение может быть по range, payload или добровольное отсечение. Последний вариант - когда инстанс сам отказывается обрабатывать пакеты
|
||||
по входящему, исходящему или обоим направлениям. Например, задача стратегии wsize - отреагировать только на пакет с tcp флагами SYN,ACK. После этого он не нужен, в коде вызывается функция отсечения.
|
||||
Это сделано для экономии ресурсов процессора.
|
||||
Если все инстансы в профиле точно никогда больше не будут вызваны по соединению + направлению - вошли в превышение верхней границы range или выполнили добровольный cutoff, то движок LUA не вызывается вообще.
|
||||
Если все инстансы в профиле точно никогда больше не будут вызваны по соединению + направлению - вошли в превышение верхней границы range или выполнили добровольный cutoff, то движок Lua не вызывается вообще.
|
||||
|
||||
От инстанса к инстансу содержимое диссекта может ими меняться. Следующий инстанс видит изменения предыдущего.
|
||||
Каждый инстанс выносит свой вердикт - что делать с текущим диссектом. VERDICT_PASS - означает отправить как есть,
|
||||
@@ -289,22 +301,21 @@ nfqws2 --lua-desync=send:ipfrag:ipfrag_pos_udp=8 --lua-desync=drop
|
||||
Но это решаемо. А что не решаемо - это перехват вторых частей kyber tls hello. Их невозможно опознать без связи с предыдущими фрагментами. Поэтому перехватывается весь порт.
|
||||
Для HTTP вопрос решаемый, поскольку там нет реассемблирования запросов, но http сейчас стал настолько редким, что и смысла нет заморачиваться.
|
||||
|
||||
Везде расставлены фильтры профиля мультистратегии `--filter-l7`, фильтры по `--out-range` и по `--payload`.
|
||||
Зачем ? В основном для сокращения вызовов LUA кода, который заведомо медленнее C кода.
|
||||
Если пакет не попадет в профили с LUA - ни о каком вызове кода LUA речи быть не может.
|
||||
Если пакет попал в профиль с LUA, то после первых 10 пакетов с данными наступает отсечение по верхней границе range. Все LUA инстансы входят в состояние instance cutoff,
|
||||
соединение входит в состояние "lua cutoff" по направлению "out". Значит вызовов LUA не будет вообще. Не просто вызовов, а даже обращения к движку LUA
|
||||
с какой-либо целью. Будет только C код, который посмотрит на признак "cutoff" и сразу же отпустит пакет.
|
||||
Везде расставлены фильтры профиля мультистратегии `--filter-l7`, фильтры по `--out-range` и по `--payload`. Зачем ? В основном для сокращения вызовов Lua кода, который заведомо медленнее C кода.
|
||||
Если пакет не попадет в профили с Lua - ни о каком вызове кода Lua речи быть не может. Если пакет попал в профиль с Lua, то после первых 10 пакетов с данными наступает отсечение по верхней границе range. Все Lua инстансы входят в состояние instance cutoff, соединение входит в состояние "lua cutoff" по направлению "out". Значит вызовов Lua не будет вообще. Не просто вызовов, а даже обращения к движку Lua с какой-либо целью. Будет только C код, который посмотрит на признак "cutoff" и сразу же отпустит пакет.
|
||||
|
||||
Так же везде расставлены фильтры по payload type. Отчасти так же с целью сократить вызовы LUA даже в пределах первых 10 пакетов с данными.
|
||||
Почему именно `-d10` ? Чтобы хватило для отработки большинства вариантов стратегий, учитывая возможные ретрансмиссии и плохую связь. В winws2 по умолчанию включен параметр `--wf-tcp-empty=0`. Он блокирует перехват пустых пакетов с ACK, что позволяет примерно в 2 раза сэкономить на процессоре при интенсивных скачиваниях. Пустые ACK в большинстве стратегий не нужны. Но это же и ломает счетчик "n" - он не будет показывать реальное количество пакетов по соединению. Счетчик "d" работать будет как надо.
|
||||
|
||||
Почему нет "-d10" на udp ? Потому что используется windivert фильтр на пейлоад. Счетчики будут считать не реальное количество пакетов в потоке, а количество перехваченных с отфильтрованными пейлоадами. Причем если интервал между ними будет более 1 минуты, то счет будет начинаться заново, поскольку таймаут udp по умолчанию - 60 сек. После таймаута запись conntrack будет удалена. Следующий пакет пойдет как новый поток.
|
||||
|
||||
Так же везде расставлены фильтры по payload type. Отчасти так же с целью сократить вызовы Lua даже в пределах первых 10 пакетов с данными.
|
||||
С другой стороны, даже при совпадении протокола соединения (`--filter-l7`) может пробежать не интересующий нас пейлоад.
|
||||
По умолчанию многие функции из `zapret-antidpi.lua` реагируют только на известные типы пейлоада, но не на конкретные, а на любые известные.
|
||||
Если допустить малореальный, но гипотетически возможный сценарий, что в рамках протокола http будет отправлен блок данных с tls или фраза, похожая на сообщение из xmpp,
|
||||
то тип пейлоада выскочит tls_client_hello или xmpp_stream, например. Лучше от этого сразу уберечься. Тем более что в других видах протоколов - xmpp, например, -
|
||||
Если допустить малореальный, но гипотетически возможный сценарий, что в рамках протокола http будет отправлен блок данных с tls или фраза, похожая на сообщение из xmpp, то тип пейлоада выскочит tls_client_hello или xmpp_stream, например. Лучше от этого сразу уберечься. Тем более что в других видах протоколов - xmpp, например, -
|
||||
пейлоады могут проскакивать нескольких типов вполне ожидаемо. Но работать надо не по всем.
|
||||
|
||||
В фейке для TLS по умолчанию - fake_default_tls - однократно при старте меняется SNI с "www.microsoft.com" на случайный и рандомизируется поле "random" в TLS handshake.
|
||||
Это делается простой строчкой LUA кода. Больше нет никаких специальных параметров *nfqws2* для модификации пейлоадов.
|
||||
Это делается простой строчкой Lua кода. Больше нет никаких специальных параметров *nfqws2* для модификации пейлоадов.
|
||||
В профиле для youtube на лету меняется SNI на "www.google.com", копируется поле TLS "session id" с обрабатываемого в данный момент TLS handshake.
|
||||
|
||||
```
|
||||
@@ -350,18 +361,15 @@ 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_binding_req,discord_ip_discovery ^
|
||||
--payload=wireguard_initiation,wireguard_cookie,stun,discord_ip_discovery ^
|
||||
--lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2
|
||||
```
|
||||
|
||||
@@ -372,9 +380,9 @@ start "zapret: http,https,quic" /min "%~dp0winws2.exe" ^
|
||||
Надо послать исходный запрос с известным пейлоадом с seqovl случайного размера от 5 до 10 символов со случайным содержимым, состоящим из букв от ‘a’ до ‘z’.
|
||||
Здесь раскрывается не декларативный характер стратегий, а алгоритмический. Стратегия - это программа, и пишите ее вы на языке программирования.
|
||||
Для облегчения простых или стандартных действий есть готовые средства, так что далеко не всегда надо писать свою функцию.
|
||||
Частенько можно обойтись простенькими кусками LUA кода в дополнение к имеющимся.
|
||||
Частенько можно обойтись простенькими кусками Lua кода в дополнение к имеющимся.
|
||||
|
||||
Здесь используется функция `luaexec`, предназначенная для динамического выполнения LUA кода в процессе обработки текущего диссекта.
|
||||
Здесь используется функция `luaexec`, предназначенная для динамического выполнения Lua кода в процессе обработки текущего диссекта.
|
||||
Она инициализирует требуемый blob, записывая его в таблицу desync, которая передается от инстанса к инстансу.
|
||||
Следующий инстанс `tcpseg` использует `rnd` как blob - источник seqovl паттерна.
|
||||
|
||||
@@ -405,4 +413,4 @@ nfqws2 \
|
||||
### Очень важный совет
|
||||
|
||||
Научитесь пользоваться `--debug` логом. Без него будет очень сложно понять *nfqws2* на начальном этапе и приспособиться к новой схеме.
|
||||
Ошибок будет много. Особенно, когда вы начнете писать свой LUA код. Их надо читать.
|
||||
Ошибок будет много. Особенно, когда вы начнете писать свой Lua код. Их надо читать.
|
||||
|
||||
BIN
files/fake/bgp_open.bin
Normal file
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.
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.
22
init.d/custom.d.examples.linux/10-keenetic-udp-fix
Normal file
22
init.d/custom.d.examples.linux/10-keenetic-udp-fix
Normal file
@@ -0,0 +1,22 @@
|
||||
# This script fixes keenetic issue with nfqws generated udp packets
|
||||
# Keenetic uses proprietary ndmmark and does not masquerade without this mark
|
||||
# If not masqueraded packets go to WAN with LAN IP and get dropped by ISP
|
||||
|
||||
# It's advised to set IFACE_WAN in config
|
||||
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - add, 0 - stop
|
||||
|
||||
local wan wanif rule
|
||||
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
# use IFACE_WAN if defined. if not - search for interfaces with default route.
|
||||
wanif=${IFACE_WAN:-$(sed -nre 's/^([^\t]+)\t00000000\t[0-9A-F]{8}\t[0-9A-F]{4}\t[0-9]+\t[0-9]+\t[0-9]+\t00000000.*$/\1/p' /proc/net/route | sort -u | xargs)}
|
||||
for wan in $wanif; do
|
||||
rule="-o $wan -p udp -m mark --mark $DESYNC_MARK/$DESYNC_MARK"
|
||||
ipt_print_op $1 "$rule" "keenetic udp fix"
|
||||
ipt_add_del $1 POSTROUTING -t nat $rule -j MASQUERADE
|
||||
done
|
||||
}
|
||||
}
|
||||
53
init.d/custom.d.examples.linux/20-fw-extra
Normal file
53
init.d/custom.d.examples.linux/20-fw-extra
Normal file
@@ -0,0 +1,53 @@
|
||||
# this custom script runs standard mode with extra firewall rules
|
||||
|
||||
# config: use NFQWS2_ENABLE_OVERRIDE to enable standard mode daemons
|
||||
# standard and override switches cannot be enabled simultaneously !
|
||||
|
||||
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_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_NFQWS2_IPT=
|
||||
#FW_EXTRA_POST_NFQWS2_NFT=
|
||||
|
||||
check_std_intersect()
|
||||
{
|
||||
[ "$NFQWS2_ENABLE_OVERRIDE" = 1 -a "$NFQWS2_ENABLE" = 1 ] && {
|
||||
echo "ERROR ! both NFQWS2_ENABLE_OVERRIDE and NFQWS2_ENABLE are enabled"
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# $1 - 1 - add, 0 - stop
|
||||
|
||||
check_std_intersect || return
|
||||
|
||||
local NFQWS2_ENABLE=$NFQWS2_ENABLE_OVERRIDE
|
||||
standard_mode_daemons "$1"
|
||||
}
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
check_std_intersect || return
|
||||
|
||||
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()
|
||||
{
|
||||
# stop logic is not required
|
||||
|
||||
check_std_intersect || return
|
||||
|
||||
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
|
||||
}
|
||||
39
init.d/custom.d.examples.linux/40-webserver
Normal file
39
init.d/custom.d.examples.linux/40-webserver
Normal file
@@ -0,0 +1,39 @@
|
||||
# this custom script runs nfqws2 in server mode for typical webserver
|
||||
|
||||
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"
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_WEBSERVER="${NFQWS_OPT_DESYNC_WEBSERVER:-$WEBSERVER_DEFAULT_STRATEGY}"
|
||||
WEBSERVER_PORTS="${WEBSERVER_PORTS:-80,443}"
|
||||
WEBSERVER_PKT_OUT="${WEBSERVER_PKT_OUT:-15}"
|
||||
|
||||
alloc_dnum DNUM_WEBSERVER
|
||||
alloc_qnum QNUM_WEBSERVER
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# $1 - 1 - add, 0 - stop
|
||||
|
||||
local opt="--qnum=$QNUM_WEBSERVER $NFQWS_OPT_DESYNC_WEBSERVER"
|
||||
do_nfqws $1 $DNUM_WEBSERVER "$opt"
|
||||
}
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local PORTS=$(replace_char - : $WEBSERVER_PORTS)
|
||||
local first_packets=$(ipt_first_packets $WEBSERVER_PKT_OUT)
|
||||
local f="-p tcp -m multiport --sports $PORTS $first_packets"
|
||||
fw_nfqws_post $1 "$f" "$f" $QNUM_WEBSERVER
|
||||
}
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
# stop logic is not required
|
||||
|
||||
local first_packets=$(nft_first_packets $WEBSERVER_PKT_OUT)
|
||||
local f="tcp sport {$WEBSERVER_PORTS} $first_packets"
|
||||
nft_fw_nfqws_post "$f" "$f" $QNUM_WEBSERVER
|
||||
}
|
||||
40
init.d/custom.d.examples.linux/50-dht4all
Normal file
40
init.d/custom.d.examples.linux/50-dht4all
Normal file
@@ -0,0 +1,40 @@
|
||||
# this custom script runs desync to DHT packets with udp payload length >=5 , without ipset/hostlist filtering
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_DHT="${NFQWS_OPT_DESYNC_DHT:---payload dht --lua-desync=dht_dn}"
|
||||
# set it to "keepalive" to fool all packets, not just the first. or set number of packets to be fooled.
|
||||
NFQWS_OPT_DHT_PKT_OUT=${NFQWS_OPT_DHT_PKT_OUT:-20}
|
||||
|
||||
alloc_dnum DNUM_DHT4ALL
|
||||
alloc_qnum QNUM_DHT4ALL
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# $1 - 1 - add, 0 - stop
|
||||
|
||||
local opt="--qnum=$QNUM_DHT4ALL $NFQWS_OPT_DESYNC_DHT"
|
||||
do_nfqws $1 $DNUM_DHT4ALL "$opt"
|
||||
}
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local f uf4 uf6
|
||||
local first_packet_only=$(ipt_first_packets $NFQWS_OPT_DHT_PKT_OUT)
|
||||
|
||||
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()
|
||||
{
|
||||
# stop logic is not required
|
||||
|
||||
local f
|
||||
local first_packet_only=$(nft_first_packets $NFQWS_OPT_DHT_PKT_OUT)
|
||||
|
||||
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
|
||||
}
|
||||
35
init.d/custom.d.examples.linux/50-discord-media
Normal file
35
init.d/custom.d.examples.linux/50-discord-media
Normal file
@@ -0,0 +1,35 @@
|
||||
# this custom script runs desync to all discord media packets
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_DISCORD_MEDIA="${NFQWS_OPT_DESYNC_DISCORD_MEDIA:---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
|
||||
alloc_qnum QNUM_DISCORD_MEDIA
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# $1 - 1 - add, 0 - stop
|
||||
|
||||
local opt="--qnum=$QNUM_DISCORD_MEDIA $NFQWS_OPT_DESYNC_DISCORD_MEDIA"
|
||||
do_nfqws $1 $DNUM_DISCORD_MEDIA "$opt"
|
||||
}
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local DISABLE_IPV6=1
|
||||
local port_range=$(replace_char - : $DISCORD_MEDIA_PORT_RANGE)
|
||||
local f="-p udp --dport $port_range -m u32 --u32"
|
||||
# this is simplified test to skip writing monstrous rule. instead of checking 64 bytes for zeroes only check 2 dwords for zero
|
||||
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=0x52&&0>>22&0x3C@8=0x00010046&&0>>22&0x3C@16=0&&0>>22&0x3C@76=0" '' $QNUM_DISCORD_MEDIA
|
||||
}
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
# stop logic is not required
|
||||
|
||||
local DISABLE_IPV6=1
|
||||
local f="udp dport $DISCORD_MEDIA_PORT_RANGE udp length == 82 @ih,0,32 0x00010046 @ih,64,128 0x00000000000000000000000000000000 @ih,192,128 0x00000000000000000000000000000000 @ih,320,128 0x00000000000000000000000000000000 @ih,448,128 0x00000000000000000000000000000000"
|
||||
nft_fw_nfqws_post "$f" '' $QNUM_DISCORD_MEDIA
|
||||
}
|
||||
144
init.d/custom.d.examples.linux/50-nfqws-ipset
Normal file
144
init.d/custom.d.examples.linux/50-nfqws-ipset
Normal file
@@ -0,0 +1,144 @@
|
||||
# this custom script demonstrates how to launch extra nfqws instance limited by ipset
|
||||
|
||||
# can override in config :
|
||||
NFQWS_MY1_OPT="${NFQWS_MY1_OPT:---filter-udp=* --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}
|
||||
|
||||
NFQWS_MY1_IPSET_SIZE=${NFQWS_MY1_IPSET_SIZE:-4096}
|
||||
NFQWS_MY1_IPSET_OPT="${NFQWS_MY1_IPSET_OPT:-hash:net hashsize 8192 maxelem $NFQWS_MY1_IPSET_SIZE}"
|
||||
|
||||
alloc_dnum DNUM_NFQWS_MY1
|
||||
alloc_qnum QNUM_NFQWS_MY1
|
||||
NFQWS_MY1_NAME4=my1nfqws4
|
||||
NFQWS_MY1_NAME6=my1nfqws6
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local opt="--qnum=$QNUM_NFQWS_MY1 $NFQWS_MY1_OPT"
|
||||
do_nfqws $1 $DNUM_NFQWS_MY1 "$opt"
|
||||
}
|
||||
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local f4 f6 subnet
|
||||
local NFQWS_MY1_PORTS_TCP=$(replace_char - : $NFQWS_MY1_PORTS_TCP)
|
||||
local NFQWS_MY1_PORTS_UDP=$(replace_char - : $NFQWS_MY1_PORTS_UDP)
|
||||
|
||||
[ "$1" = 1 -a "$DISABLE_IPV4" != 1 ] && {
|
||||
ipset create $NFQWS_MY1_NAME4 $NFQWS_MY1_IPSET_OPT family inet 2>/dev/null
|
||||
ipset flush $NFQWS_MY1_NAME4
|
||||
for subnet in $NFQWS_MY1_SUBNETS4; do
|
||||
echo add $NFQWS_MY1_NAME4 $subnet
|
||||
done | ipset -! restore
|
||||
}
|
||||
[ "$1" = 1 -a "$DISABLE_IPV6" != 1 ] && {
|
||||
ipset create $NFQWS_MY1_NAME6 $NFQWS_MY1_IPSET_OPT family inet6 2>/dev/null
|
||||
ipset flush $NFQWS_MY1_NAME6
|
||||
for subnet in $NFQWS_MY1_SUBNETS6; do
|
||||
echo add $NFQWS_MY1_NAME6 $subnet
|
||||
done | ipset -! restore
|
||||
}
|
||||
|
||||
[ -n "$NFQWS_MY1_PORTS_TCP" ] && {
|
||||
[ -n "$NFQWS_MY1_TCP_PKT_OUT" -a "$NFQWS_MY1_TCP_PKT_OUT" != 0 ] && {
|
||||
f4="-p tcp -m multiport --dports $NFQWS_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS_MY1_TCP_PKT_OUT -m set --match-set"
|
||||
f6="$f4 $NFQWS_MY1_NAME6 dst"
|
||||
f4="$f4 $NFQWS_MY1_NAME4 dst"
|
||||
fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
}
|
||||
[ -n "$NFQWS_MY1_TCP_PKT_IN" -a "$NFQWS_MY1_TCP_PKT_IN" != 0 ] && {
|
||||
f4="-p tcp -m multiport --sports $NFQWS_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS_MY1_TCP_PKT_IN -m set --match-set"
|
||||
f6="$f4 $NFQWS_MY1_NAME6 src"
|
||||
f4="$f4 $NFQWS_MY1_NAME4 src"
|
||||
fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
}
|
||||
}
|
||||
[ -n "$NFQWS_MY1_PORTS_UDP" ] && {
|
||||
[ -n "$NFQWS_MY1_UDP_PKT_OUT" -a "$NFQWS_MY1_UDP_PKT_OUT" != 0 ] && {
|
||||
f4="-p udp -m multiport --dports $NFQWS_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS_MY1_UDP_PKT_OUT -m set --match-set"
|
||||
f6="$f4 $NFQWS_MY1_NAME6 dst"
|
||||
f4="$f4 $NFQWS_MY1_NAME4 dst"
|
||||
fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
}
|
||||
[ -n "$NFQWS_MY1_UDP_PKT_IN" -a "$NFQWS_MY1_UDP_PKT_IN" != 0 ] && {
|
||||
f4="-p udp -m multiport --sports $NFQWS_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS_MY1_UDP_PKT_IN -m set --match-set"
|
||||
f6="$f4 $NFQWS_MY1_NAME6 src"
|
||||
f4="$f4 $NFQWS_MY1_NAME4 src"
|
||||
fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
}
|
||||
}
|
||||
|
||||
[ "$1" = 1 ] || {
|
||||
ipset destroy $NFQWS_MY1_NAME4 2>/dev/null
|
||||
ipset destroy $NFQWS_MY1_NAME6 2>/dev/null
|
||||
}
|
||||
}
|
||||
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
local f4 f6 subnets
|
||||
local first_packets_only="$nft_connbytes 1-$NFQWS_MY1_PKT_OUT"
|
||||
|
||||
[ "$DISABLE_IPV4" != 1 ] && {
|
||||
make_comma_list subnets $NFQWS_MY1_SUBNETS4
|
||||
nft_create_set $NFQWS_MY1_NAME4 "type ipv4_addr; size $NFQWS_MY1_IPSET_SIZE; auto-merge; flags interval;"
|
||||
nft_flush_set $NFQWS_MY1_NAME4
|
||||
nft_add_set_element $NFQWS_MY1_NAME4 "$subnets"
|
||||
}
|
||||
[ "$DISABLE_IPV6" != 1 ] && {
|
||||
make_comma_list subnets $NFQWS_MY1_SUBNETS6
|
||||
nft_create_set $NFQWS_MY1_NAME6 "type ipv6_addr; size $NFQWS_MY1_IPSET_SIZE; auto-merge; flags interval;"
|
||||
nft_flush_set $NFQWS_MY1_NAME6
|
||||
nft_add_set_element $NFQWS_MY1_NAME6 "$subnets"
|
||||
}
|
||||
|
||||
[ -n "$NFQWS_MY1_PORTS_TCP" ] && {
|
||||
[ -n "$NFQWS_MY1_TCP_PKT_OUT" -a "$NFQWS_MY1_TCP_PKT_OUT" != 0 ] && {
|
||||
f4="tcp dport {$NFQWS_MY1_PORTS_TCP} $(nft_first_packets $NFQWS_MY1_TCP_PKT_OUT)"
|
||||
f6="$f4 ip6 daddr @$NFQWS_MY1_NAME6"
|
||||
f4="$f4 ip daddr @$NFQWS_MY1_NAME4"
|
||||
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
}
|
||||
[ -n "$NFQWS_MY1_TCP_PKT_IN" -a "$NFQWS_MY1_TCP_PKT_IN" != 0 ] && {
|
||||
f4="tcp sport {$NFQWS_MY1_PORTS_TCP} $(nft_first_packets $NFQWS_MY1_TCP_PKT_IN)"
|
||||
f6="$f4 ip6 saddr @$NFQWS_MY1_NAME6"
|
||||
f4="$f4 ip saddr @$NFQWS_MY1_NAME4"
|
||||
nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
}
|
||||
}
|
||||
[ -n "$NFQWS_MY1_PORTS_UDP" ] && {
|
||||
[ -n "$NFQWS_MY1_UDP_PKT_OUT" -a "$NFQWS_MY1_UDP_PKT_OUT" != 0 ] && {
|
||||
f4="udp dport {$NFQWS_MY1_PORTS_UDP} $(nft_first_packets $NFQWS_MY1_UDP_PKT_OUT)"
|
||||
f6="$f4 ip6 daddr @$NFQWS_MY1_NAME6"
|
||||
f4="$f4 ip daddr @$NFQWS_MY1_NAME4"
|
||||
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
}
|
||||
[ -n "$NFQWS_MY1_UDP_PKT_IN" -a "$NFQWS_MY1_UDP_PKT_IN" != 0 ] && {
|
||||
f4="udp sport {$NFQWS_MY1_PORTS_UDP} $(nft_first_packets $NFQWS_MY1_UDP_PKT_IN)"
|
||||
f6="$f4 ip6 saddr @$NFQWS_MY1_NAME6"
|
||||
f4="$f4 ip saddr @$NFQWS_MY1_NAME4"
|
||||
nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
zapret_custom_firewall_nft_flush()
|
||||
{
|
||||
# this function is called after all nft fw rules are deleted
|
||||
# however sets are not deleted. it's desired to clear sets here.
|
||||
|
||||
nft_del_set $NFQWS_MY1_NAME4 2>/dev/null
|
||||
nft_del_set $NFQWS_MY1_NAME6 2>/dev/null
|
||||
}
|
||||
30
init.d/custom.d.examples.linux/50-quic4all
Normal file
30
init.d/custom.d.examples.linux/50-quic4all
Normal file
@@ -0,0 +1,30 @@
|
||||
# this custom script runs desync to all IETF QUIC initials
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_QUIC="${NFQWS_OPT_DESYNC_QUIC:---payload quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=2}"
|
||||
|
||||
alloc_dnum DNUM_QUIC4ALL
|
||||
alloc_qnum QNUM_QUIC4ALL
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# $1 - 1 - add, 0 - stop
|
||||
|
||||
local opt="--qnum=$QNUM_QUIC4ALL $NFQWS_OPT_DESYNC_QUIC"
|
||||
do_nfqws $1 $DNUM_QUIC4ALL "$opt"
|
||||
}
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local f='-p udp -m u32 --u32'
|
||||
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=264:65535&&0>>22&0x3C@8>>28=0xC&&0>>22&0x3C@9=0x00000001" "$f 44>>16=264:65535&&48>>28=0xC&&49=0x00000001" $QNUM_QUIC4ALL
|
||||
}
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
# stop logic is not required
|
||||
|
||||
local f="udp length >= 264 @ih,0,4 0xC @ih,8,32 0x00000001"
|
||||
nft_fw_nfqws_post "$f" "$f" $QNUM_QUIC4ALL
|
||||
}
|
||||
30
init.d/custom.d.examples.linux/50-stun4all
Normal file
30
init.d/custom.d.examples.linux/50-stun4all
Normal file
@@ -0,0 +1,30 @@
|
||||
# this custom script runs desync to all stun packets
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_STUN="${NFQWS_OPT_DESYNC_STUN:---payload stun --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
|
||||
|
||||
alloc_dnum DNUM_STUN4ALL
|
||||
alloc_qnum QNUM_STUN4ALL
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# $1 - 1 - add, 0 - stop
|
||||
|
||||
local opt="--qnum=$QNUM_STUN4ALL $NFQWS_OPT_DESYNC_STUN"
|
||||
do_nfqws $1 $DNUM_STUN4ALL "$opt"
|
||||
}
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local f='-p udp -m u32 --u32'
|
||||
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=28:65535&&0>>22&0x3C@12=0x2112A442&&0>>22&0x3C@8&0xC0000003=0" "$f 44>>16=28:65535&&52=0x2112A442&&48&0xC0000003=0" $QNUM_STUN4ALL
|
||||
}
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
# stop logic is not required
|
||||
|
||||
local f="udp length >= 28 @ih,32,32 0x2112A442 @ih,0,2 0 @ih,30,2 0"
|
||||
nft_fw_nfqws_post "$f" "$f" $QNUM_STUN4ALL
|
||||
}
|
||||
38
init.d/custom.d.examples.linux/50-wg4all
Normal file
38
init.d/custom.d.examples.linux/50-wg4all
Normal file
@@ -0,0 +1,38 @@
|
||||
# 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,wireguard_response,wireguard_cookie --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
|
||||
|
||||
alloc_dnum DNUM_WG4ALL
|
||||
alloc_qnum QNUM_WG4ALL
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# $1 - 1 - add, 0 - stop
|
||||
|
||||
local opt="--qnum=$QNUM_WG4ALL $NFQWS_OPT_DESYNC_WG"
|
||||
do_nfqws $1 $DNUM_WG4ALL "$opt"
|
||||
}
|
||||
# size = 156 (8 udp header + 148 payload) && payload starts with 0x01000000
|
||||
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=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()
|
||||
{
|
||||
# stop logic is not required
|
||||
|
||||
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
|
||||
}
|
||||
69
init.d/openrc/zapret2
Executable file
69
init.d/openrc/zapret2
Executable file
@@ -0,0 +1,69 @@
|
||||
#!/sbin/openrc-run
|
||||
|
||||
# zapret openrc to sysv adapter
|
||||
# on some systems (alpine) for unknown reason non-openrc-run scripts are not started from /etc/init.d
|
||||
|
||||
EXEDIR=$(dirname "$RC_SERVICE")
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
ZAPRET_BASE="$EXEDIR/../.."
|
||||
ZAPRET_INIT="$ZAPRET_BASE/init.d/sysv/zapret2"
|
||||
|
||||
extra_commands="start_fw stop_fw restart_fw start_daemons stop_daemons restart_daemons reload_ifsets list_ifsets list_table"
|
||||
description="extra commands :"
|
||||
description_stop_fw="Stop zapret firewall"
|
||||
description_start_fw="Start zapret firewall"
|
||||
description_restart_fw="Restart zapret firewall"
|
||||
description_reload_ifsets="Reload interface lists (nftables only)"
|
||||
description_list_ifsets="Display interface lists (nftables only)"
|
||||
description_list_table="Display zapret nftable (nftables only)"
|
||||
description_stop_daemons="Stop zapret daemons only"
|
||||
description_start_daemons="Start zapret daemons only"
|
||||
description_restart_daemons="Restart zapret firewall only"
|
||||
|
||||
depend() {
|
||||
rc-service -e networking && need networking
|
||||
}
|
||||
start()
|
||||
{
|
||||
"$ZAPRET_INIT" start
|
||||
}
|
||||
stop()
|
||||
{
|
||||
"$ZAPRET_INIT" stop
|
||||
}
|
||||
start_fw()
|
||||
{
|
||||
"$ZAPRET_INIT" start_fw
|
||||
}
|
||||
stop_fw()
|
||||
{
|
||||
"$ZAPRET_INIT" stop_fw
|
||||
}
|
||||
restart_fw()
|
||||
{
|
||||
"$ZAPRET_INIT" restart_fw
|
||||
}
|
||||
start_daemons()
|
||||
{
|
||||
"$ZAPRET_INIT" start_daemons
|
||||
}
|
||||
stop_daemons()
|
||||
{
|
||||
"$ZAPRET_INIT" stop_daemons
|
||||
}
|
||||
restart_daemons()
|
||||
{
|
||||
"$ZAPRET_INIT" restart_daemons
|
||||
}
|
||||
reload_ifsets()
|
||||
{
|
||||
"$ZAPRET_INIT" reload_ifsets
|
||||
}
|
||||
list_ifsets()
|
||||
{
|
||||
"$ZAPRET_INIT" list_ifsets
|
||||
}
|
||||
list_table()
|
||||
{
|
||||
"$ZAPRET_INIT" list_table
|
||||
}
|
||||
33
init.d/openwrt/90-zapret2
Normal file
33
init.d/openwrt/90-zapret2
Normal file
@@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
|
||||
ZAPRET=/etc/init.d/zapret2
|
||||
|
||||
[ -n "$INTERFACE" ] && [ "$ACTION" = ifup -o "$ACTION" = ifdown ] && [ -x "$ZAPRET" ] && "$ZAPRET" enabled && {
|
||||
SCRIPT=$(readlink "$ZAPRET")
|
||||
if [ -n "$SCRIPT" ]; then
|
||||
EXEDIR=$(dirname "$SCRIPT")
|
||||
ZAPRET_BASE=$(readlink -f "$EXEDIR/../..")
|
||||
else
|
||||
ZAPRET_BASE=/opt/zapret2
|
||||
fi
|
||||
ZAPRET_RW=${ZAPRET_RW:-"$ZAPRET_BASE"}
|
||||
ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"}
|
||||
CUSTOM_DIR="$ZAPRET_RW/init.d/openwrt"
|
||||
. "$ZAPRET_CONFIG"
|
||||
. "$ZAPRET_BASE/common/base.sh"
|
||||
. "$ZAPRET_BASE/common/fwtype.sh"
|
||||
|
||||
linux_fwtype
|
||||
case "$FWTYPE" in
|
||||
nftables)
|
||||
logger -t zapret reloading nftables ifsets due to $ACTION of $INTERFACE
|
||||
"$ZAPRET" reload_ifsets
|
||||
;;
|
||||
iptables)
|
||||
openwrt_fw3 || {
|
||||
logger -t zapret reloading iptables due to $ACTION of $INTERFACE
|
||||
"$ZAPRET" restart_fw
|
||||
}
|
||||
;;
|
||||
esac
|
||||
}
|
||||
0
init.d/openwrt/custom.d/.keep
Normal file
0
init.d/openwrt/custom.d/.keep
Normal file
11
init.d/openwrt/firewall.zapret2
Normal file
11
init.d/openwrt/firewall.zapret2
Normal file
@@ -0,0 +1,11 @@
|
||||
SCRIPT=$(readlink /etc/init.d/zapret2)
|
||||
if [ -n "$SCRIPT" ]; then
|
||||
EXEDIR=$(dirname "$SCRIPT")
|
||||
ZAPRET_BASE=$(readlink -f "$EXEDIR/../..")
|
||||
else
|
||||
ZAPRET_BASE=/opt/zapret2
|
||||
fi
|
||||
|
||||
. "$ZAPRET_BASE/init.d/openwrt/functions"
|
||||
|
||||
zapret_apply_firewall
|
||||
218
init.d/openwrt/functions
Normal file
218
init.d/openwrt/functions
Normal file
@@ -0,0 +1,218 @@
|
||||
. /lib/functions/network.sh
|
||||
|
||||
ZAPRET_BASE=${ZAPRET_BASE:-/opt/zapret2}
|
||||
ZAPRET_RW=${ZAPRET_RW:-"$ZAPRET_BASE"}
|
||||
ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"}
|
||||
. "$ZAPRET_CONFIG"
|
||||
. "$ZAPRET_BASE/common/base.sh"
|
||||
. "$ZAPRET_BASE/common/fwtype.sh"
|
||||
. "$ZAPRET_BASE/common/linux_iphelper.sh"
|
||||
. "$ZAPRET_BASE/common/ipt.sh"
|
||||
. "$ZAPRET_BASE/common/nft.sh"
|
||||
. "$ZAPRET_BASE/common/linux_fw.sh"
|
||||
. "$ZAPRET_BASE/common/linux_daemons.sh"
|
||||
. "$ZAPRET_BASE/common/list.sh"
|
||||
. "$ZAPRET_BASE/common/custom.sh"
|
||||
CUSTOM_DIR="$ZAPRET_RW/init.d/openwrt"
|
||||
|
||||
QNUM=${QNUM:-300}
|
||||
WS_USER=${WS_USER:-daemon}
|
||||
DESYNC_MARK=${DESYNC_MARK:-0x40000000}
|
||||
DESYNC_MARK_POSTNAT=${DESYNC_MARK_POSTNAT:-0x20000000}
|
||||
OPENWRT_LAN=${OPENWRT_LAN:-lan}
|
||||
|
||||
IPSET_CR="$ZAPRET_BASE/ipset/create_ipset.sh"
|
||||
|
||||
# can be multiple ipv6 outgoing interfaces
|
||||
# uplink from isp, tunnelbroker, vpn, ...
|
||||
# want them all. who knows what's the real one that blocks sites
|
||||
# dont want any manual configuration - want to do it automatically
|
||||
# standard network_find_wan[6] return only the first
|
||||
# we use low level function from network.sh to avoid this limitation
|
||||
# it can change theoretically and stop working
|
||||
|
||||
network_find_wan4_all()
|
||||
{
|
||||
if [ -n "$OPENWRT_WAN4" ]; then
|
||||
eval $1="\$OPENWRT_WAN4"
|
||||
else
|
||||
__network_ifstatus "$1" "" "[@.route[@.target='0.0.0.0' && !@.table]].interface" "" 10 2>/dev/null && return
|
||||
network_find_wan $1
|
||||
fi
|
||||
}
|
||||
network_find_wan_all()
|
||||
{
|
||||
network_find_wan4_all "$@"
|
||||
}
|
||||
network_find_wan6_all()
|
||||
{
|
||||
if [ -n "$OPENWRT_WAN6" ]; then
|
||||
eval $1="\$OPENWRT_WAN6"
|
||||
else
|
||||
__network_ifstatus "$1" "" "[@.route[@.target='::' && !@.table]].interface" "" 10 2>/dev/null && return
|
||||
network_find_wan6 $1
|
||||
fi
|
||||
}
|
||||
network_find_wanX_devices()
|
||||
{
|
||||
# $1 - ip version: 4 or 6
|
||||
# $2 - variable to put result to
|
||||
local ifaces
|
||||
network_find_wan${1}_all ifaces
|
||||
call_for_multiple_items network_get_device $2 "$ifaces"
|
||||
}
|
||||
|
||||
|
||||
fw_nfqws_prepost_x()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - filter
|
||||
# $3 - queue number
|
||||
# $4 - 4/6
|
||||
# $5 - post/pre
|
||||
|
||||
local ifaces DWAN
|
||||
network_find_wan${4}_all ifaces
|
||||
call_for_multiple_items network_get_device DWAN "$ifaces"
|
||||
|
||||
[ -n "$DWAN" ] && _fw_nfqws_${5}${4} $1 "$2" $3 "$(unique $DWAN)"
|
||||
}
|
||||
fw_nfqws_post4()
|
||||
{
|
||||
fw_nfqws_prepost_x $1 "$2" $3 4 post
|
||||
}
|
||||
fw_nfqws_post6()
|
||||
{
|
||||
fw_nfqws_prepost_x $1 "$2" $3 6 post
|
||||
}
|
||||
fw_nfqws_pre4()
|
||||
{
|
||||
fw_nfqws_prepost_x $1 "$2" $3 4 pre
|
||||
}
|
||||
fw_nfqws_pre6()
|
||||
{
|
||||
fw_nfqws_prepost_x $1 "$2" $3 6 pre
|
||||
}
|
||||
|
||||
create_ipset()
|
||||
{
|
||||
echo "Creating ip list table (firewall type $FWTYPE)"
|
||||
"$IPSET_CR" "$@"
|
||||
}
|
||||
|
||||
list_nfqws_rules()
|
||||
{
|
||||
# $1 = '' for ipv4, '6' for ipv6
|
||||
ip$1tables -S POSTROUTING -t mangle | \
|
||||
grep -E "NFQUEUE --queue-num $QNUM --queue-bypass|NFQUEUE --queue-num $(($QNUM+1)) --queue-bypass|NFQUEUE --queue-num $(($QNUM+2)) --queue-bypass|NFQUEUE --queue-num $(($QNUM+3)) --queue-bypass|NFQUEUE --queue-num $(($QNUM+10)) --queue-bypass|NFQUEUE --queue-num $(($QNUM+11)) --queue-bypass" | \
|
||||
sed -re 's/^-A POSTROUTING (.*) -j NFQUEUE.*$/\1/' -e "s/-m mark ! --mark $DESYNC_MARK\/$DESYNC_MARK//"
|
||||
}
|
||||
apply_flow_offloading_enable_rule()
|
||||
{
|
||||
# $1 = '' for ipv4, '6' for ipv6
|
||||
local i off='-j FLOWOFFLOAD'
|
||||
[ "$FLOWOFFLOAD" = "hardware" ] && off="$off --hw"
|
||||
i="forwarding_rule_zapret -m comment --comment zapret_traffic_offloading_enable -m conntrack --ctstate RELATED,ESTABLISHED $off"
|
||||
echo enabling ipv${1:-4} flow offloading : $i
|
||||
ip$1tables -A $i
|
||||
}
|
||||
apply_flow_offloading_exempt_rule()
|
||||
{
|
||||
# $1 = '' for ipv4, '6' for ipv6
|
||||
local i v
|
||||
v=$1
|
||||
shift
|
||||
i="forwarding_rule_zapret $@ -m comment --comment zapret_traffic_offloading_exemption -j RETURN"
|
||||
echo applying ipv${v:-4} flow offloading exemption : $i
|
||||
ip${v}tables -A $i
|
||||
}
|
||||
flow_offloading_unexempt_v()
|
||||
{
|
||||
# $1 = '' for ipv4, '6' for ipv6
|
||||
local DWAN
|
||||
network_find_wanX_devices ${1:-4} DWAN
|
||||
for i in $DWAN; do ipt$1_del FORWARD -o $i -j forwarding_rule_zapret ; done
|
||||
ip$1tables -F forwarding_rule_zapret 2>/dev/null
|
||||
ip$1tables -X forwarding_rule_zapret 2>/dev/null
|
||||
}
|
||||
flow_offloading_exempt_v()
|
||||
{
|
||||
# $1 = '' for ipv4, '6' for ipv6
|
||||
is_ipt_flow_offload_avail $1 || return 0
|
||||
|
||||
flow_offloading_unexempt_v $1
|
||||
|
||||
[ "$FLOWOFFLOAD" = 'software' -o "$FLOWOFFLOAD" = 'hardware' ] && {
|
||||
ip$1tables -N forwarding_rule_zapret
|
||||
|
||||
# remove outgoing interface
|
||||
list_nfqws_rules $1 | sed -re 's/-o +[^ ]+//g' |
|
||||
while read rule; do
|
||||
apply_flow_offloading_exempt_rule "$1" $rule
|
||||
done
|
||||
|
||||
apply_flow_offloading_enable_rule $1
|
||||
|
||||
# only outgoing to WAN packets trigger flow offloading
|
||||
local DWAN
|
||||
network_find_wanX_devices ${1:-4} DWAN
|
||||
for i in $DWAN; do ipt$1 FORWARD -o $i -j forwarding_rule_zapret; done
|
||||
}
|
||||
return 0
|
||||
}
|
||||
flow_offloading_exempt()
|
||||
{
|
||||
[ "$DISABLE_IPV4" = "1" ] || flow_offloading_exempt_v
|
||||
[ "$DISABLE_IPV6" = "1" ] || flow_offloading_exempt_v 6
|
||||
}
|
||||
flow_offloading_unexempt()
|
||||
{
|
||||
[ "$DISABLE_IPV4" = "1" ] || flow_offloading_unexempt_v
|
||||
[ "$DISABLE_IPV6" = "1" ] || flow_offloading_unexempt_v 6
|
||||
}
|
||||
|
||||
nft_fill_ifsets_overload()
|
||||
{
|
||||
local ifaces DLAN DWAN DWAN6 PDLAN PDWAN PDWAN6
|
||||
|
||||
call_for_multiple_items network_get_device DLAN "$OPENWRT_LAN"
|
||||
call_for_multiple_items network_get_physdev PDLAN "$OPENWRT_LAN"
|
||||
|
||||
network_find_wan4_all ifaces
|
||||
call_for_multiple_items network_get_device DWAN "$ifaces"
|
||||
call_for_multiple_items network_get_physdev PDWAN "$ifaces"
|
||||
|
||||
network_find_wan6_all ifaces
|
||||
call_for_multiple_items network_get_device DWAN6 "$ifaces"
|
||||
call_for_multiple_items network_get_physdev PDWAN6 "$ifaces"
|
||||
|
||||
nft_fill_ifsets "$DLAN" "$DWAN" "$DWAN6" "$PDLAN" "$PDWAN" "$PDWAN6"
|
||||
}
|
||||
nft_wanif_filter_present()
|
||||
{
|
||||
# in openwrt we always use wanif filter
|
||||
return 0
|
||||
}
|
||||
nft_wanif6_filter_present()
|
||||
{
|
||||
# in openwrt we always use wanif6 filter
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
nft_fw_nfqws_post4()
|
||||
{
|
||||
_nft_fw_nfqws_post4 "$1" $2 always_apply_wan_filter
|
||||
}
|
||||
nft_fw_nfqws_post6()
|
||||
{
|
||||
_nft_fw_nfqws_post6 "$1" $2 always_apply_wan_filter
|
||||
}
|
||||
nft_fw_nfqws_pre4()
|
||||
{
|
||||
_nft_fw_nfqws_pre4 "$1" $2 always_apply_wan_filter
|
||||
}
|
||||
nft_fw_nfqws_pre6()
|
||||
{
|
||||
_nft_fw_nfqws_pre6 "$1" $2 always_apply_wan_filter
|
||||
}
|
||||
135
init.d/openwrt/zapret2
Executable file
135
init.d/openwrt/zapret2
Executable file
@@ -0,0 +1,135 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
USE_PROCD=1
|
||||
# after network
|
||||
START=21
|
||||
|
||||
my_extra_command() {
|
||||
local cmd="$1"
|
||||
local help="$2"
|
||||
|
||||
local extra="$(printf "%-16s%s" "${cmd}" "${help}")"
|
||||
EXTRA_HELP="${EXTRA_HELP} ${extra}
|
||||
"
|
||||
EXTRA_COMMANDS="${EXTRA_COMMANDS} ${cmd}"
|
||||
}
|
||||
my_extra_command stop_fw "Stop zapret firewall (noop in iptables+fw3 case)"
|
||||
my_extra_command start_fw "Start zapret firewall (noop in iptables+fw3 case)"
|
||||
my_extra_command restart_fw "Restart zapret firewall (noop in iptables+fw3 case)"
|
||||
my_extra_command reload_ifsets "Reload interface lists (nftables only)"
|
||||
my_extra_command list_ifsets "Display interface lists (nftables only)"
|
||||
my_extra_command list_table "Display zapret nftable (nftables only)"
|
||||
my_extra_command stop_daemons "Stop zapret daemons only (=stop in iptables+fw3 case)"
|
||||
my_extra_command start_daemons "Start zapret daemons only (=start in iptables+fw3 case)"
|
||||
my_extra_command restart_daemons "Restart zapret firewall only (=restart in iptables+fw3 case)"
|
||||
|
||||
SCRIPT=$(readlink /etc/init.d/zapret2)
|
||||
if [ -n "$SCRIPT" ]; then
|
||||
EXEDIR=$(dirname "$SCRIPT")
|
||||
ZAPRET_BASE=$(readlink -f "$EXEDIR/../..")
|
||||
else
|
||||
ZAPRET_BASE=/opt/zapret2
|
||||
fi
|
||||
|
||||
. "$ZAPRET_BASE/init.d/openwrt/functions"
|
||||
|
||||
|
||||
# !!!!! in old openwrt 21.x- with iptables firewall rules are configured separately
|
||||
# !!!!! in new openwrt >21.x with nftables firewall is configured here
|
||||
|
||||
PIDDIR=/var/run
|
||||
|
||||
USEROPT="--user=$WS_USER"
|
||||
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"
|
||||
|
||||
run_daemon()
|
||||
{
|
||||
# $1 - daemon string id or number. can use 1,2,3,...
|
||||
# $2 - daemon
|
||||
# $3 - daemon args
|
||||
# use $PIDDIR/$DAEMONBASE$1.pid as pidfile
|
||||
local DAEMONBASE="$(basename "$2")"
|
||||
echo "Starting daemon $1: $2 $3"
|
||||
procd_open_instance
|
||||
procd_set_param command $2 $3
|
||||
procd_set_param pidfile $PIDDIR/${DAEMONBASE}_$1.pid
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
run_nfqws()
|
||||
{
|
||||
run_daemon $1 "$NFQWS2" "$NFQWS2_OPT_BASE $2"
|
||||
}
|
||||
do_nfqws()
|
||||
{
|
||||
[ "$1" = 0 ] || { shift; run_nfqws "$@"; }
|
||||
}
|
||||
|
||||
start_daemons_procd()
|
||||
{
|
||||
standard_mode_daemons 1
|
||||
custom_runner zapret_custom_daemons 1
|
||||
|
||||
return 0
|
||||
}
|
||||
start_daemons()
|
||||
{
|
||||
rc_procd start_daemons_procd "$@"
|
||||
}
|
||||
stop_daemons()
|
||||
{
|
||||
local svc="$(basename ${basescript:-$initscript})"
|
||||
procd_running "$svc" "$1" && procd_kill "$svc" "$1"
|
||||
}
|
||||
restart_daemons()
|
||||
{
|
||||
stop_daemons
|
||||
start_daemons
|
||||
}
|
||||
|
||||
start_fw()
|
||||
{
|
||||
zapret_apply_firewall
|
||||
}
|
||||
stop_fw()
|
||||
{
|
||||
zapret_unapply_firewall
|
||||
}
|
||||
restart_fw()
|
||||
{
|
||||
stop_fw
|
||||
start_fw
|
||||
}
|
||||
reload_ifsets()
|
||||
{
|
||||
zapret_reload_ifsets
|
||||
}
|
||||
list_ifsets()
|
||||
{
|
||||
zapret_list_ifsets
|
||||
}
|
||||
list_table()
|
||||
{
|
||||
zapret_list_table
|
||||
}
|
||||
|
||||
start_service()
|
||||
{
|
||||
start_daemons_procd
|
||||
[ "$INIT_APPLY_FW" != "1" ] || {
|
||||
linux_fwtype
|
||||
openwrt_fw3_integration || start_fw
|
||||
}
|
||||
}
|
||||
|
||||
stop_service()
|
||||
{
|
||||
# this procedure is called from stop()
|
||||
# stop() already stop daemons
|
||||
[ "$INIT_APPLY_FW" != "1" ] || {
|
||||
linux_fwtype
|
||||
openwrt_fw3_integration || stop_fw
|
||||
}
|
||||
}
|
||||
27
init.d/pfsense/zapret2.sh
Executable file
27
init.d/pfsense/zapret2.sh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
|
||||
# this file should be placed to /usr/local/etc/rc.d and chmod 755
|
||||
|
||||
# copy 'lua' dir there
|
||||
ZDIR=/usr/local/etc/zapret2
|
||||
|
||||
# prepare system
|
||||
|
||||
kldload ipfw
|
||||
kldload ipdivert
|
||||
|
||||
# for older pfsense versions. newer do not have these sysctls
|
||||
sysctl net.inet.ip.pfil.outbound=ipfw,pf
|
||||
sysctl net.inet.ip.pfil.inbound=ipfw,pf
|
||||
sysctl net.inet6.ip6.pfil.outbound=ipfw,pf
|
||||
sysctl net.inet6.ip6.pfil.inbound=ipfw,pf
|
||||
|
||||
# required for newer pfsense versions (2.6.0 tested) to return ipfw to functional state
|
||||
pfctl -d ; pfctl -e
|
||||
|
||||
# add ipfw rules and start daemon
|
||||
|
||||
ipfw delete 100
|
||||
ipfw add 100 divert 990 tcp from any to any 80,443 out not diverted not sockarg
|
||||
pkill ^dvtws2$
|
||||
dvtws2 --daemon --port 990 --lua-init=@$ZDIR/zapret-lib.lua --lua-init=@$ZDIR/zapret-antidpi.lua --lua-desync=multisplit
|
||||
2
init.d/runit/zapret2/finish
Executable file
2
init.d/runit/zapret2/finish
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
/opt/zapret2/init.d/sysv/zapret2 stop
|
||||
3
init.d/runit/zapret2/run
Executable file
3
init.d/runit/zapret2/run
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
/opt/zapret2/init.d/sysv/zapret2 start
|
||||
exec chpst -b zapret2 sleep infinity
|
||||
2
init.d/s6/zapret2/down
Executable file
2
init.d/s6/zapret2/down
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/execlineb -P
|
||||
exec /opt/zapret2/init.d/sysv/zapret2 stop
|
||||
1
init.d/s6/zapret2/type
Normal file
1
init.d/s6/zapret2/type
Normal file
@@ -0,0 +1 @@
|
||||
oneshot
|
||||
2
init.d/s6/zapret2/up
Executable file
2
init.d/s6/zapret2/up
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/execlineb -P
|
||||
exec /opt/zapret2/init.d/sysv/zapret2 start
|
||||
62
init.d/systemd/nfqws2@.service
Normal file
62
init.d/systemd/nfqws2@.service
Normal file
@@ -0,0 +1,62 @@
|
||||
# Example systemd service unit for nfqws. Adjust for your installation.
|
||||
|
||||
# WARNING ! This unit requires to compile nfqws using `make systemd`
|
||||
# WARNING ! This makefile target enables special systemd notify support.
|
||||
|
||||
# PREPARE
|
||||
# install build depends
|
||||
# make -C /opt/zapret2 systemd
|
||||
# cp nfqws2\@.service /lib/systemd/system
|
||||
# systemctl daemon-reload
|
||||
|
||||
# MANAGE INSTANCE
|
||||
# prepare /etc/zapret2/nfqws1.conf with nfqws parameters
|
||||
# systemctl start nfqws2@nfqws1
|
||||
# systemctl status nfqws2@nfqws1
|
||||
# systemctl restart nfqws2@nfqws1
|
||||
# systemctl enable nfqws2@nfqws1
|
||||
# systemctl disable nfqws2@nfqws1
|
||||
# systemctl stop nfqws2@nfqws1
|
||||
|
||||
# DELETE
|
||||
# rm /lib/systemd/system/nfqws@.service
|
||||
# systemctl daemon-reload
|
||||
|
||||
|
||||
[Unit]
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
Restart=on-failure
|
||||
|
||||
ExecSearchPath=/opt/zapret2/nfq2
|
||||
ExecStart=nfqws2 @${CONFIG_DIR}/${INSTANCE}.conf
|
||||
Environment=CONFIG_DIR=/etc/zapret2
|
||||
Environment=INSTANCE=%i
|
||||
|
||||
RestrictAddressFamilies=AF_NETLINK AF_UNIX AF_INET6 AF_INET
|
||||
|
||||
LockPersonality=true
|
||||
MemoryDenyWriteExecute=true
|
||||
PrivateDevices=true
|
||||
PrivateMounts=true
|
||||
PrivateTmp=true
|
||||
ProcSubset=pid
|
||||
ProtectClock=true
|
||||
ProtectControlGroups=true
|
||||
ProtectHome=true
|
||||
ProtectHostname=true
|
||||
ProtectKernelLogs=true
|
||||
ProtectKernelModules=true
|
||||
ProtectKernelTunables=true
|
||||
ProtectProc=invisible
|
||||
ProtectSystem=full
|
||||
RemoveIPC=true
|
||||
RestrictNamespaces=true
|
||||
RestrictRealtime=true
|
||||
RestrictSUIDSGID=true
|
||||
UMask=0077
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
13
init.d/systemd/zapret2-list-update.service
Normal file
13
init.d/systemd/zapret2-list-update.service
Normal file
@@ -0,0 +1,13 @@
|
||||
[Unit]
|
||||
Description=zapret2 ip/host list update
|
||||
|
||||
[Service]
|
||||
Restart=no
|
||||
IgnoreSIGPIPE=no
|
||||
KillMode=control-group
|
||||
GuessMainPID=no
|
||||
RemainAfterExit=no
|
||||
ExecStart=/opt/zapret2/ipset/get_config.sh
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
11
init.d/systemd/zapret2-list-update.timer
Normal file
11
init.d/systemd/zapret2-list-update.timer
Normal file
@@ -0,0 +1,11 @@
|
||||
[Unit]
|
||||
Description=zapret2 ip/host list update timer
|
||||
|
||||
[Timer]
|
||||
OnCalendar=*-*-2,4,6,8,10,12,14,16,18,20,22,24,26,28,30 00:00:00
|
||||
RandomizedDelaySec=86400
|
||||
Persistent=true
|
||||
Unit=zapret2-list-update.service
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
17
init.d/systemd/zapret2.service
Normal file
17
init.d/systemd/zapret2.service
Normal file
@@ -0,0 +1,17 @@
|
||||
[Unit]
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
Restart=no
|
||||
TimeoutSec=30sec
|
||||
IgnoreSIGPIPE=no
|
||||
KillMode=none
|
||||
GuessMainPID=no
|
||||
RemainAfterExit=no
|
||||
ExecStart=/opt/zapret2/init.d/sysv/zapret2 start
|
||||
ExecStop=/opt/zapret2/init.d/sysv/zapret2 stop
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
0
init.d/sysv/custom.d/.keep
Normal file
0
init.d/sysv/custom.d/.keep
Normal file
191
init.d/sysv/functions
Normal file
191
init.d/sysv/functions
Normal file
@@ -0,0 +1,191 @@
|
||||
# init script functions library for desktop linux systems
|
||||
|
||||
ZAPRET_BASE=${ZAPRET_BASE:-/opt/zapret2}
|
||||
ZAPRET_RW=${ZAPRET_RW:-"$ZAPRET_BASE"}
|
||||
ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"}
|
||||
. "$ZAPRET_CONFIG"
|
||||
. "$ZAPRET_BASE/common/base.sh"
|
||||
. "$ZAPRET_BASE/common/fwtype.sh"
|
||||
. "$ZAPRET_BASE/common/linux_iphelper.sh"
|
||||
. "$ZAPRET_BASE/common/ipt.sh"
|
||||
. "$ZAPRET_BASE/common/nft.sh"
|
||||
. "$ZAPRET_BASE/common/linux_fw.sh"
|
||||
. "$ZAPRET_BASE/common/linux_daemons.sh"
|
||||
. "$ZAPRET_BASE/common/list.sh"
|
||||
. "$ZAPRET_BASE/common/custom.sh"
|
||||
CUSTOM_DIR="$ZAPRET_RW/init.d/sysv"
|
||||
|
||||
|
||||
user_exists()
|
||||
{
|
||||
id -u $1 >/dev/null 2>/dev/null
|
||||
}
|
||||
useradd_compat()
|
||||
{
|
||||
# $1 - username
|
||||
# skip for readonly systems
|
||||
[ -w "/etc" ] && {
|
||||
if exists useradd ; then
|
||||
useradd --no-create-home --system --shell /bin/false $1
|
||||
elif is_linked_to_busybox adduser ; then
|
||||
# some systems may miss nogroup group in /etc/group
|
||||
# adduser fails if it's absent and no group is specified
|
||||
addgroup nogroup 2>/dev/null
|
||||
# busybox has special adduser syntax
|
||||
adduser -S -H -D $1
|
||||
elif exists adduser; then
|
||||
adduser --no-create-home --system --disabled-login $1
|
||||
fi
|
||||
}
|
||||
user_exists $1
|
||||
}
|
||||
prepare_user()
|
||||
{
|
||||
user_exists $WS_USER || {
|
||||
# fallback to daemon if we cant add WS_USER
|
||||
useradd_compat $WS_USER || {
|
||||
for user in daemon nobody; do
|
||||
user_exists $user && {
|
||||
WS_USER=$user
|
||||
return 0
|
||||
}
|
||||
done
|
||||
return 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# this complex user selection allows to survive in any locked/readonly/minimalistic environment
|
||||
[ -n "$WS_USER" ] || WS_USER=tpws
|
||||
if prepare_user; then
|
||||
USEROPT="--user=$WS_USER"
|
||||
else
|
||||
WS_USER=1
|
||||
USEROPT="--uid $WS_USER:$WS_USER"
|
||||
fi
|
||||
|
||||
PIDDIR=/var/run
|
||||
IPSET_CR="$ZAPRET_BASE/ipset/create_ipset.sh"
|
||||
|
||||
DESYNC_MARK=${DESYNC_MARK:-0x40000000}
|
||||
DESYNC_MARK_POSTNAT=${DESYNC_MARK_POSTNAT:-0x20000000}
|
||||
|
||||
QNUM=${QNUM:-300}
|
||||
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"
|
||||
|
||||
|
||||
fw_nfqws_post4()
|
||||
{
|
||||
_fw_nfqws_post4 $1 "$2" $3 "$IFACE_WAN"
|
||||
}
|
||||
fw_nfqws_post6()
|
||||
{
|
||||
_fw_nfqws_post6 $1 "$2" $3 "${IFACE_WAN6:-$IFACE_WAN}"
|
||||
}
|
||||
fw_nfqws_pre4()
|
||||
{
|
||||
_fw_nfqws_pre4 $1 "$2" $3 "$IFACE_WAN"
|
||||
}
|
||||
fw_nfqws_pre6()
|
||||
{
|
||||
_fw_nfqws_pre6 $1 "$2" $3 "${IFACE_WAN6:-$IFACE_WAN}"
|
||||
}
|
||||
nft_fw_nfqws_post4()
|
||||
{
|
||||
_nft_fw_nfqws_post4 "$1" $2 "$IFACE_WAN"
|
||||
}
|
||||
nft_fw_nfqws_post6()
|
||||
{
|
||||
_nft_fw_nfqws_post6 "$1" $2 "${IFACE_WAN6:-$IFACE_WAN}"
|
||||
}
|
||||
nft_fw_nfqws_pre4()
|
||||
{
|
||||
_nft_fw_nfqws_pre4 "$1" $2 "$IFACE_WAN"
|
||||
}
|
||||
nft_fw_nfqws_pre6()
|
||||
{
|
||||
_nft_fw_nfqws_pre6 "$1" $2 "${IFACE_WAN6:-$IFACE_WAN}"
|
||||
}
|
||||
|
||||
nft_wanif_filter_present()
|
||||
{
|
||||
[ -n "$IFACE_WAN" ]
|
||||
}
|
||||
nft_wanif6_filter_present()
|
||||
{
|
||||
[ -n "${IFACE_WAN6:-$IFACE_WAN}" ]
|
||||
}
|
||||
nft_fill_ifsets_overload()
|
||||
{
|
||||
nft_fill_ifsets "$IFACE_WAN" "${IFACE_WAN6:-$IFACE_WAN}" "$IFACE_LAN"
|
||||
}
|
||||
|
||||
|
||||
run_daemon()
|
||||
{
|
||||
# $1 - daemon number : 1,2,3,...
|
||||
# $2 - daemon
|
||||
# $3 - daemon args
|
||||
# use $PIDDIR/$DAEMONBASE$1.pid as pidfile
|
||||
|
||||
local DAEMONBASE="$(basename "$2")"
|
||||
local PID= PIDFILE=$PIDDIR/${DAEMONBASE}_$1.pid
|
||||
echo "Starting daemon $1: $2 $3"
|
||||
|
||||
[ -f "$PIDFILE" ] && {
|
||||
read PID <"$PIDFILE"
|
||||
[ -d "/proc/$PID" ] || PID=
|
||||
}
|
||||
|
||||
if [ -n "$PID" ]; then
|
||||
echo already running
|
||||
else
|
||||
"$2" $3 >/dev/null &
|
||||
PID=$!
|
||||
if [ -n "$PID" ]; then
|
||||
echo $PID >$PIDFILE
|
||||
else
|
||||
echo could not start daemon $1 : $2 $3
|
||||
false
|
||||
fi
|
||||
fi
|
||||
}
|
||||
stop_daemon()
|
||||
{
|
||||
# $1 - daemon number : 1,2,3,...
|
||||
# $2 - daemon
|
||||
# use $PIDDIR/$DAEMONBASE$1.pid as pidfile
|
||||
local DAEMONBASE="$(basename "$2")"
|
||||
local PID PIDFILE=$PIDDIR/${DAEMONBASE}_$1.pid
|
||||
echo "Stopping daemon $1: $2"
|
||||
if [ -f "$PIDFILE" ]; then
|
||||
read PID <"$PIDFILE"
|
||||
kill $PID
|
||||
rm -f "$PIDFILE"
|
||||
else
|
||||
echo no pidfile : $PIDFILE
|
||||
fi
|
||||
}
|
||||
do_daemon()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
on_off_function run_daemon stop_daemon "$@"
|
||||
}
|
||||
|
||||
do_nfqws()
|
||||
{
|
||||
# $1 : 1 - run, 0 - stop
|
||||
# $2 : daemon number
|
||||
# $3 : daemon args
|
||||
|
||||
do_daemon $1 $2 "$NFQWS2" "$NFQWS2_OPT_BASE $3"
|
||||
}
|
||||
|
||||
|
||||
create_ipset()
|
||||
{
|
||||
echo "Creating ip list table (firewall type $FWTYPE)"
|
||||
"$IPSET_CR" "$@"
|
||||
}
|
||||
82
init.d/sysv/zapret2
Executable file
82
init.d/sysv/zapret2
Executable file
@@ -0,0 +1,82 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: zapret
|
||||
# Required-Start: $local_fs $network
|
||||
# Required-Stop: $local_fs $network
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
### END INIT INFO
|
||||
|
||||
SCRIPT=$(readlink -f "$0")
|
||||
EXEDIR=$(dirname "$SCRIPT")
|
||||
ZAPRET_BASE=$(readlink -f "$EXEDIR/../..")
|
||||
. "$EXEDIR/functions"
|
||||
|
||||
NAME=zapret
|
||||
DESC=anti-zapret
|
||||
|
||||
do_start()
|
||||
{
|
||||
zapret_run_daemons
|
||||
[ "$INIT_APPLY_FW" != "1" ] || { zapret_apply_firewall; }
|
||||
}
|
||||
do_stop()
|
||||
{
|
||||
zapret_stop_daemons
|
||||
[ "$INIT_APPLY_FW" != "1" ] || zapret_unapply_firewall
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
do_start
|
||||
;;
|
||||
|
||||
stop)
|
||||
do_stop
|
||||
;;
|
||||
|
||||
restart)
|
||||
do_stop
|
||||
do_start
|
||||
;;
|
||||
|
||||
start-fw|start_fw)
|
||||
zapret_apply_firewall
|
||||
;;
|
||||
stop-fw|stop_fw)
|
||||
zapret_unapply_firewall
|
||||
;;
|
||||
|
||||
restart-fw|restart_fw)
|
||||
zapret_unapply_firewall
|
||||
zapret_apply_firewall
|
||||
;;
|
||||
|
||||
start-daemons|start_daemons)
|
||||
zapret_run_daemons
|
||||
;;
|
||||
stop-daemons|stop_daemons)
|
||||
zapret_stop_daemons
|
||||
;;
|
||||
restart-daemons|restart_daemons)
|
||||
zapret_stop_daemons
|
||||
zapret_run_daemons
|
||||
;;
|
||||
|
||||
reload-ifsets|reload_ifsets)
|
||||
zapret_reload_ifsets
|
||||
;;
|
||||
list-ifsets|list_ifsets)
|
||||
zapret_list_ifsets
|
||||
;;
|
||||
list-table|list_table)
|
||||
zapret_list_table
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Usage: $SCRIPT {start|stop|restart|start-fw|stop-fw|restart-fw|start-daemons|stop-daemons|restart-daemons|reload-ifsets|list-ifsets|list-table}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
14
init.d/windivert.filter.examples/README.txt
Normal file
14
init.d/windivert.filter.examples/README.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
Цель этих фильтров - отсекать полезную нагрузку в режиме ядра, не насилуя процессор перенаправлением целого потока на winws.
|
||||
Задействуются через `winws --wf-raw-part=@filename`. Может быть несколько частичных фильтров. Они могут сочетаться с --wf-tcp и --wf-udp.
|
||||
Однако, язык фильтров windivert не содержит операций с битовыми полями, сдвигов и побитовой логики.
|
||||
Поэтому фильтры получились более слабыми, способными передавать неправильную нагрузку.
|
||||
Дофильтрация производится силами winws.
|
||||
|
||||
Описание языка фильтров : https://reqrypt.org/windivert-doc.html#filter_language
|
||||
Пример инстанса для пробития медиапотоков в discord : `winws --wf-raw-part=@windivert_part.discord_media.txt --wf-raw-part=@windivert_part.stun.txt --filter-l7=stun,discord --dpi-desync=fake`
|
||||
|
||||
|
||||
These filters are invoked using `winws --wf-raw-part=@filename`. Multiple filter parts are supported. They can be combined with --wf-tcp and --wf-udp.
|
||||
Filters are kernel mode and save great amount of CPU.
|
||||
However windivert cannot filter by bit fields, lacks shift and bitwise logic operations.
|
||||
Filters are relaxed and can pass wrong payloads. Finer filtering is done by winws.
|
||||
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
|
||||
@@ -0,0 +1,20 @@
|
||||
outbound and ip and
|
||||
udp.DstPort>=50000 and udp.DstPort<=50099 and
|
||||
udp.PayloadLength=74 and
|
||||
udp.Payload32[0]=0x00010046 and
|
||||
udp.Payload32[2]=0 and
|
||||
udp.Payload32[3]=0 and
|
||||
udp.Payload32[4]=0 and
|
||||
udp.Payload32[5]=0 and
|
||||
udp.Payload32[6]=0 and
|
||||
udp.Payload32[7]=0 and
|
||||
udp.Payload32[8]=0 and
|
||||
udp.Payload32[9]=0 and
|
||||
udp.Payload32[10]=0 and
|
||||
udp.Payload32[11]=0 and
|
||||
udp.Payload32[12]=0 and
|
||||
udp.Payload32[13]=0 and
|
||||
udp.Payload32[14]=0 and
|
||||
udp.Payload32[15]=0 and
|
||||
udp.Payload32[16]=0 and
|
||||
udp.Payload32[17]=0
|
||||
@@ -0,0 +1,4 @@
|
||||
outbound and
|
||||
udp.PayloadLength>=256 and
|
||||
udp.Payload[0]>=0xC0 and udp.Payload[0]<0xD0 and
|
||||
udp.Payload[1]=0 and udp.Payload16[1]=0 and udp.Payload[4]=1
|
||||
3
init.d/windivert.filter.examples/windivert_part.stun.txt
Normal file
3
init.d/windivert.filter.examples/windivert_part.stun.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
outbound and
|
||||
udp.PayloadLength>=20 and
|
||||
udp.Payload32[1]=0x2112A442 and udp.Payload[0]<0x40
|
||||
@@ -0,0 +1,3 @@
|
||||
udp.PayloadLength=148 and udp.Payload[0]=0x01 or
|
||||
udp.PayloadLength=92 and udp.Payload[0]=0x02 or
|
||||
udp.PayloadLength=64 and udp.Payload[0]=0x03
|
||||
@@ -30,7 +30,7 @@ select_test_method()
|
||||
TEST=bash
|
||||
elif exists zsh && [ "$UNAME" != CYGWIN ] ; then
|
||||
TEST=zsh
|
||||
elif [ "$UNAME" != Darwin -a "$UNAME" != CYGWIN ]; then
|
||||
elif [ "$UNAME" != CYGWIN ]; then
|
||||
if exists hexdump and exists dd; then
|
||||
# macos does not use ELF
|
||||
TEST=elf
|
||||
@@ -64,12 +64,6 @@ select_test_method()
|
||||
|
||||
}
|
||||
|
||||
disable_antivirus()
|
||||
{
|
||||
# $1 - dir
|
||||
[ "$UNAME" = Darwin ] && find "$1" -maxdepth 1 -type f -perm +111 -exec xattr -d com.apple.quarantine {} \; 2>/dev/null
|
||||
}
|
||||
|
||||
check_dir()
|
||||
{
|
||||
local dir="$BINDIR/$1"
|
||||
@@ -77,7 +71,6 @@ check_dir()
|
||||
local out
|
||||
if [ -f "$exe" ]; then
|
||||
if [ -x "$exe" ]; then
|
||||
disable_antivirus "$dir"
|
||||
case $TEST in
|
||||
bash)
|
||||
out=$(echo 0.0.0.0 | bash -c "\"$exe"\" 2>/dev/null)
|
||||
@@ -143,8 +136,7 @@ if [ ! -d "$BINDIR" ] || ! dir_is_not_empty "$BINDIR" ]; then
|
||||
echo "to compile on other systems : make"
|
||||
;;
|
||||
Darwin)
|
||||
echo "you need to download release from github or build binaries from source"
|
||||
echo "to compile : make mac"
|
||||
echo "macos is not supported"
|
||||
;;
|
||||
FreeBSD)
|
||||
echo "you need to download release from github or build binaries from source"
|
||||
@@ -168,9 +160,6 @@ case $UNAME in
|
||||
ARCHLIST="my linux-x86_64 linux-x86 linux-arm64 linux-arm linux-mips64 linux-mipsel linux-mips linux-lexra linux-ppc"
|
||||
PKTWS=nfqws2
|
||||
;;
|
||||
Darwin)
|
||||
ARCHLIST="my mac64"
|
||||
;;
|
||||
FreeBSD)
|
||||
ARCHLIST="my freebsd-x86_64"
|
||||
PKTWS=dvtws2
|
||||
|
||||
833
install_easy.sh
Executable file
833
install_easy.sh
Executable file
@@ -0,0 +1,833 @@
|
||||
#!/bin/sh
|
||||
|
||||
# automated script for easy installing zapret
|
||||
|
||||
EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
ZAPRET_BASE=${ZAPRET_BASE:-"$EXEDIR"}
|
||||
ZAPRET_TARGET=${ZAPRET_TARGET:-/opt/zapret2}
|
||||
ZAPRET_TARGET_RW=${ZAPRET_RW:-"$ZAPRET_TARGET"}
|
||||
ZAPRET_TARGET_CONFIG="$ZAPRET_TARGET_RW/config"
|
||||
ZAPRET_RW=${ZAPRET_RW:-"$ZAPRET_BASE"}
|
||||
ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"}
|
||||
ZAPRET_CONFIG_DEFAULT="$ZAPRET_BASE/config.default"
|
||||
IPSET_DIR="$ZAPRET_BASE/ipset"
|
||||
|
||||
[ -f "$ZAPRET_CONFIG" ] || {
|
||||
ZAPRET_CONFIG_DIR="$(dirname "$ZAPRET_CONFIG")"
|
||||
[ -d "$ZAPRET_CONFIG_DIR" ] || mkdir -p "$ZAPRET_CONFIG_DIR"
|
||||
cp "$ZAPRET_CONFIG_DEFAULT" "$ZAPRET_CONFIG"
|
||||
}
|
||||
. "$ZAPRET_CONFIG"
|
||||
. "$ZAPRET_BASE/common/base.sh"
|
||||
. "$ZAPRET_BASE/common/elevate.sh"
|
||||
. "$ZAPRET_BASE/common/fwtype.sh"
|
||||
. "$ZAPRET_BASE/common/dialog.sh"
|
||||
. "$ZAPRET_BASE/common/ipt.sh"
|
||||
. "$ZAPRET_BASE/common/installer.sh"
|
||||
. "$ZAPRET_BASE/common/virt.sh"
|
||||
. "$ZAPRET_BASE/common/list.sh"
|
||||
|
||||
GET_LIST="$IPSET_DIR/get_config.sh"
|
||||
|
||||
check_readonly_system()
|
||||
{
|
||||
local RO
|
||||
echo \* checking readonly system
|
||||
case $SYSTEM in
|
||||
systemd)
|
||||
[ -w "$SYSTEMD_SYSTEM_DIR" ] || RO=1
|
||||
;;
|
||||
openrc)
|
||||
[ -w "$(dirname "$INIT_SCRIPT")" ] || RO=1
|
||||
;;
|
||||
esac
|
||||
[ -z "$RO" ] || {
|
||||
echo '!!! READONLY SYSTEM DETECTED !!!'
|
||||
echo '!!! WILL NOT BE ABLE TO CONFIGURE STARTUP !!!'
|
||||
echo '!!! MANUAL STARTUP CONFIGURATION IS REQUIRED !!!'
|
||||
ask_yes_no N "do you want to continue" || exitp 5
|
||||
}
|
||||
}
|
||||
|
||||
check_source()
|
||||
{
|
||||
local bad=0
|
||||
|
||||
echo \* checking source files
|
||||
case $SYSTEM in
|
||||
systemd)
|
||||
[ -f "$EXEDIR/init.d/systemd/zapret2.service" ] || bad=1
|
||||
;;
|
||||
openrc)
|
||||
[ -f "$EXEDIR/init.d/openrc/zapret2" ] || bad=1
|
||||
;;
|
||||
esac
|
||||
[ "$bad" = 1 ] && {
|
||||
echo 'some critical files are missing'
|
||||
echo 'are you sure you are not using embedded release ? you need full version for traditional systems'
|
||||
exitp 5
|
||||
}
|
||||
}
|
||||
|
||||
check_bins()
|
||||
{
|
||||
echo \* checking executables
|
||||
|
||||
fix_perms_bin_test "$EXEDIR"
|
||||
local arch="$(get_bin_arch)"
|
||||
local make_target
|
||||
local cf="-march=native"
|
||||
[ "$FORCE_BUILD" = "1" ] && {
|
||||
echo forced build mode
|
||||
if [ "$arch" = "my" ]; then
|
||||
echo already compiled
|
||||
else
|
||||
arch=""
|
||||
fi
|
||||
}
|
||||
if [ -n "$arch" ] ; then
|
||||
echo found architecture "\"$arch\""
|
||||
elif [ -f "$EXEDIR/Makefile" ] && exists make; then
|
||||
echo trying to compile
|
||||
case $SYSTEM in
|
||||
systemd)
|
||||
make_target=systemd
|
||||
;;
|
||||
esac
|
||||
CFLAGS="${cf:+$cf }${CFLAGS}" OPTIMIZE=-O2 make -C "$EXEDIR" $make_target || {
|
||||
echo could not compile
|
||||
make -C "$EXEDIR" clean
|
||||
exitp 8
|
||||
}
|
||||
echo compiled
|
||||
else
|
||||
echo build tools not found
|
||||
exitp 8
|
||||
fi
|
||||
}
|
||||
|
||||
call_install_bin()
|
||||
{
|
||||
sh "$EXEDIR/install_bin.sh" $1
|
||||
}
|
||||
get_bin_arch()
|
||||
{
|
||||
call_install_bin getarch
|
||||
}
|
||||
|
||||
install_binaries()
|
||||
{
|
||||
echo \* installing binaries
|
||||
|
||||
call_install_bin || {
|
||||
echo compatible binaries not found
|
||||
exitp 8
|
||||
}
|
||||
}
|
||||
|
||||
ws_opt_validate()
|
||||
{
|
||||
# ПРИМЕЧАНИЕ ДЛЯ РАСПРОСТРАНИТЕЛЕЙ КОПИПАСТЫ
|
||||
# ЭТОТ КОД СДЕЛАН СПЕЦИАЛЬНО ДЛЯ ВАС, ЧТОБЫ ВЫ НЕ ПОСТИЛИ В СЕТЬ ПЛОХИЕ РЕЦЕПТЫ
|
||||
# ЕСЛИ ВАМ ХОЧЕТСЯ ЕГО УДАЛИТЬ И НАПИСАТЬ ИНСТРУКЦИЮ КАК ЕГО УДАЛЯТЬ, ВЫ ДЕЛАЕТЕ ХРЕНОВУЮ УСЛУГУ. НАПИШИТЕ ЛУЧШЕ custom script.
|
||||
# custom script - ЭТО ФАЙЛИК, КОТОРЫЙ ДОСТАТОЧНО СКОПИРОВАТЬ В НУЖНУЮ ДИРЕКТОРИЮ, ЧТОБЫ ОН СДЕЛАЛ ТОЖЕ САМОЕ, НО ЭФФЕКТИВНО.
|
||||
# ФИЛЬТРАЦИЯ ПО IPSET В ЯДРЕ НЕСРАВНИМО ЭФФЕКТИВНЕЕ, ЧЕМ ПЕРЕКИДЫВАТЬ ВСЕ ПАКЕТЫ В nfqws И ТАМ ФИЛЬТРОВАТЬ
|
||||
# --ipset СУЩЕСТВУЕТ ТОЛЬКО ДЛЯ ВИНДЫ И LINUX СИСТЕМ БЕЗ ipset (НАПРИМЕР, Android).
|
||||
# И ТОЛЬКО ПО ЭТОЙ ПРИЧИНЕ ОНО НЕ ВЫКИНУТО ПОЛНОСТЬЮ ИЗ LINUX ВЕРСИИ
|
||||
has_bad_ws_options "$1" && {
|
||||
help_bad_ws_options
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
nfqws_opt_validate()
|
||||
{
|
||||
ws_opt_validate "$1" || return 1
|
||||
dry_run_nfqws || {
|
||||
echo invalid nfqws2 options
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
select_mode_group()
|
||||
{
|
||||
# $1 - ENABLE var name
|
||||
# $2 - ask text
|
||||
# $3 - vars
|
||||
# $4 - validator func
|
||||
# $5 - validator func param var
|
||||
|
||||
local enabled var v edited bad Y param
|
||||
|
||||
echo
|
||||
ask_yes_no_var $1 "$2"
|
||||
write_config_var $1
|
||||
eval enabled=\$$1
|
||||
[ "$enabled" = 1 ] && {
|
||||
echo
|
||||
while : ; do
|
||||
list_vars $3
|
||||
bad=0; Y=N
|
||||
[ -n "$4" ] && {
|
||||
eval param="\$$5"
|
||||
$4 "$param"; bad=$?
|
||||
[ "$bad" = 1 ] && Y=Y
|
||||
}
|
||||
ask_yes_no $Y "do you want to edit the options" || {
|
||||
[ "$bad" = 1 ] && {
|
||||
echo installer will not allow to use bad options. exiting.
|
||||
exitp 3
|
||||
}
|
||||
[ -n "$edited" ] && {
|
||||
for var in $3; do
|
||||
write_config_var $var
|
||||
done
|
||||
}
|
||||
break
|
||||
}
|
||||
edit_vars $3
|
||||
edited=1
|
||||
echo ..edited..
|
||||
done
|
||||
}
|
||||
}
|
||||
|
||||
select_mode_nfqws()
|
||||
{
|
||||
local EDITVAR_NEWLINE_DELIMETERS="--new --out-range --in-range --payload" EDITVAR_NEWLINE_VARS="NFQWS2_OPT"
|
||||
select_mode_group NFQWS2_ENABLE "enable nfqws2 ?" "NFQWS2_PORTS_TCP NFQWS2_PORTS_UDP NFQWS2_TCP_PKT_OUT NFQWS2_TCP_PKT_IN NFQWS2_UDP_PKT_OUT NFQWS2_UDP_PKT_IN NFQWS2_PORTS_TCP_KEEPALIVE NFQWS2_PORTS_UDP_KEEPALIVE NFQWS2_OPT" nfqws_opt_validate NFQWS2_OPT
|
||||
}
|
||||
|
||||
select_mode_mode()
|
||||
{
|
||||
select_mode_nfqws
|
||||
|
||||
echo
|
||||
echo "current custom scripts in $CUSTOM_DIR/custom.d:"
|
||||
[ -d "$CUSTOM_DIR/custom.d" ] && ls "$CUSTOM_DIR/custom.d"
|
||||
echo "Make sure this is ok"
|
||||
echo
|
||||
}
|
||||
|
||||
select_mode_filter()
|
||||
{
|
||||
local filter="none ipset hostlist autohostlist"
|
||||
echo
|
||||
echo select filtering :
|
||||
ask_list MODE_FILTER "$filter" none && write_config_var MODE_FILTER
|
||||
}
|
||||
|
||||
select_mode()
|
||||
{
|
||||
select_mode_filter
|
||||
select_mode_mode
|
||||
select_mode_iface
|
||||
}
|
||||
|
||||
select_getlist()
|
||||
{
|
||||
if [ "$MODE_FILTER" = "ipset" -o "$MODE_FILTER" = "hostlist" -o "$MODE_FILTER" = "autohostlist" ]; then
|
||||
local D=N
|
||||
[ -n "$GETLIST" ] && D=Y
|
||||
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"
|
||||
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_preresolved.sh get_reestr_preresolved_smart.sh"
|
||||
GETLIST_DEF="get_antifilter_allyouneed.sh"
|
||||
fi
|
||||
ask_list GETLIST "$GETLISTS" "$GETLIST_DEF" && write_config_var GETLIST
|
||||
return
|
||||
fi
|
||||
fi
|
||||
GETLIST=""
|
||||
write_config_var GETLIST
|
||||
}
|
||||
|
||||
ask_config()
|
||||
{
|
||||
select_mode
|
||||
select_getlist
|
||||
}
|
||||
|
||||
ask_config_offload()
|
||||
{
|
||||
[ "$FWTYPE" = nftables ] || is_ipt_flow_offload_avail && {
|
||||
echo
|
||||
echo flow offloading can greatly increase speed on slow devices and high speed links \(usually 150+ mbits\)
|
||||
if [ "$SYSTEM" = openwrt ]; then
|
||||
echo unfortuantely its not compatible with most nfqws options. nfqws traffic must be exempted from flow offloading.
|
||||
echo donttouch = disable system flow offloading setting if nfqws mode was selected, dont touch it otherwise and dont configure selective flow offloading
|
||||
echo none = always disable system flow offloading setting and dont configure selective flow offloading
|
||||
echo software = always disable system flow offloading setting and configure selective software flow offloading
|
||||
echo hardware = always disable system flow offloading setting and configure selective hardware flow offloading
|
||||
else
|
||||
echo offloading is applicable only to forwarded traffic. it has no effect on outgoing traffic
|
||||
echo hardware flow offloading is available only on specific supporting hardware. most likely will not work on a generic system
|
||||
fi
|
||||
echo offloading likely breaks traffic shaper
|
||||
echo select flow offloading :
|
||||
local options="none software hardware"
|
||||
local default="none"
|
||||
[ "$SYSTEM" = openwrt ] && {
|
||||
options="donttouch none software hardware"
|
||||
default="donttouch"
|
||||
}
|
||||
ask_list FLOWOFFLOAD "$options" $default && write_config_var FLOWOFFLOAD
|
||||
}
|
||||
}
|
||||
|
||||
ask_config_tmpdir()
|
||||
{
|
||||
# ask tmpdir change for low ram systems with enough free disk space
|
||||
[ -n "$GETLIST" ] && [ $(get_free_space_mb "$EXEDIR/tmp") -ge 128 ] && [ $(get_ram_mb) -le 400 ] && {
|
||||
echo
|
||||
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 select temp file location
|
||||
[ -z "$TMPDIR" ] && TMPDIR=/tmp
|
||||
ask_list TMPDIR "/tmp $EXEDIR/tmp" && {
|
||||
[ "$TMPDIR" = "/tmp" ] && TMPDIR=
|
||||
write_config_var TMPDIR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nft_flow_offload()
|
||||
{
|
||||
[ "$UNAME" = Linux -a "$FWTYPE" = nftables ] && [ "$FLOWOFFLOAD" = software -o "$FLOWOFFLOAD" = hardware ]
|
||||
}
|
||||
|
||||
ask_iface()
|
||||
{
|
||||
# $1 - var to ask
|
||||
# $2 - additional name for empty string synonim
|
||||
|
||||
local ifs i0 def new
|
||||
eval def="\$$1"
|
||||
|
||||
[ -n "$2" ] && i0="$2 "
|
||||
ifs="$(ls /sys/class/net)"
|
||||
[ -z "$def" ] && eval $1="$2"
|
||||
ask_list $1 "$i0$ifs" && {
|
||||
eval new="\$$1"
|
||||
[ "$new" = "$2" ] && eval $1=""
|
||||
write_config_var $1
|
||||
}
|
||||
}
|
||||
ask_iface_lan()
|
||||
{
|
||||
echo LAN interface :
|
||||
local opt
|
||||
nft_flow_offload || opt=NONE
|
||||
ask_iface IFACE_LAN $opt
|
||||
}
|
||||
ask_iface_wan()
|
||||
{
|
||||
echo WAN interface :
|
||||
local opt
|
||||
nft_flow_offload || opt=ANY
|
||||
ask_iface IFACE_WAN $opt
|
||||
}
|
||||
|
||||
select_mode_iface()
|
||||
{
|
||||
# openwrt has its own interface management scheme
|
||||
# LAN interface names are used only to setup flow offloading rules
|
||||
|
||||
[ "$SYSTEM" = "openwrt" ] && return
|
||||
|
||||
ask_iface_lan
|
||||
ask_iface_wan
|
||||
}
|
||||
|
||||
default_files()
|
||||
{
|
||||
# $1 - ro location
|
||||
# $2 - rw location (can be equal to $1)
|
||||
[ -d "$2/ipset" ] || mkdir -p "$2/ipset"
|
||||
[ -f "$2/ipset/zapret-hosts-user-exclude.txt" ] || cp "$1/ipset/zapret-hosts-user-exclude.txt.default" "$2/ipset/zapret-hosts-user-exclude.txt"
|
||||
[ -f "$2/ipset/zapret-hosts-user.txt" ] || echo nonexistent.domain >> "$2/ipset/zapret-hosts-user.txt"
|
||||
[ -f "$2/ipset/zapret-hosts-user-ipban.txt" ] || touch "$2/ipset/zapret-hosts-user-ipban.txt"
|
||||
for dir in openwrt sysv macos; do
|
||||
[ -d "$1/init.d/$dir" ] && {
|
||||
[ -d "$2/init.d/$dir" ] || mkdir -p "$2/init.d/$dir"
|
||||
[ -d "$2/init.d/$dir/custom.d" ] || mkdir -p "$2/init.d/$dir/custom.d"
|
||||
}
|
||||
done
|
||||
}
|
||||
copy_all()
|
||||
{
|
||||
local dir
|
||||
|
||||
cp -R "$1" "$2"
|
||||
[ -d "$2/tmp" ] || mkdir "$2/tmp"
|
||||
}
|
||||
copy_openwrt()
|
||||
{
|
||||
local ARCH="$(get_bin_arch)"
|
||||
local BINDIR="$1/binaries/$ARCH"
|
||||
local file
|
||||
|
||||
[ -d "$2" ] || mkdir -p "$2"
|
||||
|
||||
mkdir "$2/nfq2" "$2/ip2net" "$2/mdig" "$2/binaries" "$2/binaries/$ARCH" "$2/init.d" "$2/tmp" "$2/files"
|
||||
cp -R "$1/files/fake" "$2/files"
|
||||
cp -R "$1/common" "$1/ipset" "$1/blockcheck2.d" "$1/lua" "$2"
|
||||
cp -R "$1/init.d/openwrt" "$1/init.d/custom.d.examples.linux" "$2/init.d"
|
||||
cp "$1/config" "$1/config.default" "$1/install_easy.sh" "$1/uninstall_easy.sh" "$1/install_bin.sh" "$1/install_prereq.sh" "$1/blockcheck2.sh" "$2"
|
||||
cp "$BINDIR/nfqws2" "$BINDIR/ip2net" "$BINDIR/mdig" "$2/binaries/$ARCH"
|
||||
}
|
||||
|
||||
fix_perms_bin_test()
|
||||
{
|
||||
[ -d "$1" ] || return
|
||||
find "$1/binaries" -name ip2net ! -perm -111 -exec chmod +x {} \;
|
||||
}
|
||||
fix_perms()
|
||||
{
|
||||
[ -d "$1" ] || return
|
||||
find "$1" -type d -exec chmod 755 {} \;
|
||||
find "$1" -type f -exec chmod 644 {} \;
|
||||
local chow
|
||||
case "$UNAME" in
|
||||
Linux)
|
||||
chow=root:root
|
||||
;;
|
||||
*)
|
||||
chow=root:wheel
|
||||
esac
|
||||
chown -R $chow "$1"
|
||||
find "$1/binaries" '(' -name dvtws2 -o -name nfqws2 -o -name ip2net -o -name mdig ')' -exec chmod 755 {} \;
|
||||
for f in \
|
||||
install_bin.sh \
|
||||
blockcheck2.sh \
|
||||
install_easy.sh \
|
||||
install_prereq.sh \
|
||||
files/huawei/E8372/zapret-ip \
|
||||
files/huawei/E8372/unzapret-ip \
|
||||
files/huawei/E8372/run-zapret-hostlist \
|
||||
files/huawei/E8372/unzapret \
|
||||
files/huawei/E8372/zapret \
|
||||
files/huawei/E8372/run-zapret-ip \
|
||||
ipset/get_exclude.sh \
|
||||
ipset/clear_lists.sh \
|
||||
ipset/create_ipset.sh \
|
||||
ipset/get_config.sh \
|
||||
ipset/get_user.sh \
|
||||
ipset/get_ipban.sh \
|
||||
ipset/get_refilter_domains.sh \
|
||||
ipset/get_refilter_ipsum.sh \
|
||||
ipset/get_reestr_resolvable_domains.sh \
|
||||
ipset/get_reestr_preresolved.sh \
|
||||
ipset/get_reestr_preresolved_smart.sh \
|
||||
ipset/get_reestr_resolve.sh \
|
||||
ipset/get_reestr_hostlist.sh \
|
||||
ipset/get_antifilter_allyouneed.sh \
|
||||
ipset/get_antifilter_ipsum.sh \
|
||||
ipset/get_antifilter_ipsmart.sh \
|
||||
ipset/get_antifilter_ip.sh \
|
||||
ipset/get_antifilter_ipresolve.sh \
|
||||
ipset/get_antizapret_domains.sh \
|
||||
init.d/pfsense/zapret2.sh \
|
||||
init.d/runit/zapret2/run \
|
||||
init.d/runit/zapret2/finish \
|
||||
init.d/openrc/zapret2 \
|
||||
init.d/sysv/zapret2 \
|
||||
init.d/openwrt/zapret2 \
|
||||
uninstall_easy.sh \
|
||||
; do chmod 755 "$1/$f" 2>/dev/null ; done
|
||||
}
|
||||
|
||||
|
||||
_backup_settings()
|
||||
{
|
||||
local i=0
|
||||
for f in "$@"; do
|
||||
# safety check
|
||||
[ -z "$f" -o "$f" = "/" ] && continue
|
||||
|
||||
[ -f "$ZAPRET_TARGET/$f" ] && cp -f "$ZAPRET_TARGET/$f" "/tmp/zapret2-bkp-$i"
|
||||
[ -d "$ZAPRET_TARGET/$f" ] && cp -rf "$ZAPRET_TARGET/$f" "/tmp/zapret2-bkp-$i"
|
||||
i=$(($i+1))
|
||||
done
|
||||
}
|
||||
_restore_settings()
|
||||
{
|
||||
local i=0
|
||||
for f in "$@"; do
|
||||
# safety check
|
||||
[ -z "$f" -o "$f" = "/" ] && continue
|
||||
|
||||
[ -f "/tmp/zapret2-bkp-$i" ] && {
|
||||
mv -f "/tmp/zapret2-bkp-$i" "$ZAPRET_TARGET/$f" || rm -f "/tmp/zapret2-bkp-$i"
|
||||
}
|
||||
[ -d "/tmp/zapret2-bkp-$i" ] && {
|
||||
[ -d "$ZAPRET_TARGET/$f" ] && rm -r "$ZAPRET_TARGET/$f"
|
||||
mv -f "/tmp/zapret2-bkp-$i" "$ZAPRET_TARGET/$f" || rm -r "/tmp/zapret2-bkp-$i"
|
||||
}
|
||||
i=$(($i+1))
|
||||
done
|
||||
}
|
||||
backup_restore_settings()
|
||||
{
|
||||
# $1 - 1 - backup, 0 - restore
|
||||
local mode=$1
|
||||
on_off_function _backup_settings _restore_settings $mode "config" "init.d/sysv/custom.d" "init.d/openwrt/custom.d" "ipset/zapret-hosts-user.txt" "ipset/zapret-hosts-user-exclude.txt" "ipset/zapret-hosts-user-ipban.txt" "ipset/zapret-hosts-auto.txt"
|
||||
}
|
||||
|
||||
check_location()
|
||||
{
|
||||
# $1 - copy function
|
||||
|
||||
echo \* checking location
|
||||
# use inodes in case something is linked
|
||||
if [ -d "$ZAPRET_TARGET" ] && [ $(get_dir_inode "$EXEDIR") = $(get_dir_inode "$ZAPRET_TARGET") ]; then
|
||||
default_files "$ZAPRET_TARGET" "$ZAPRET_RW"
|
||||
else
|
||||
local rwdir=0
|
||||
[ $(get_dir_inode "$ZAPRET_BASE") = $(get_dir_inode "$ZAPRET_RW") ] || rwdir=1
|
||||
echo
|
||||
echo easy install is supported only from default location : $ZAPRET_TARGET
|
||||
echo currently its run from $EXEDIR
|
||||
if ask_yes_no N "do you want the installer to copy it for you"; then
|
||||
local keep=N
|
||||
if [ -d "$ZAPRET_TARGET" ]; then
|
||||
echo
|
||||
echo installer found existing $ZAPRET_TARGET
|
||||
echo directory needs to be replaced. config and custom scripts can be kept or replaced with clean version
|
||||
if ask_yes_no N "do you want to delete all files there and copy this version"; then
|
||||
echo
|
||||
if [ $rwdir != 1 ]; then
|
||||
ask_yes_no Y "keep config, custom scripts and user lists" && keep=Y
|
||||
[ "$keep" = "Y" ] && backup_restore_settings 1
|
||||
fi
|
||||
rm -r "$ZAPRET_TARGET"
|
||||
else
|
||||
echo refused to overwrite $ZAPRET_TARGET. exiting
|
||||
exitp 3
|
||||
fi
|
||||
fi
|
||||
local B="$(dirname "$ZAPRET_TARGET")"
|
||||
[ -d "$B" ] || mkdir -p "$B"
|
||||
$1 "$EXEDIR" "$ZAPRET_TARGET"
|
||||
fix_perms "$ZAPRET_TARGET"
|
||||
[ "$keep" = "Y" ] && backup_restore_settings 0
|
||||
echo relaunching itself from $ZAPRET_TARGET
|
||||
exec "$ZAPRET_TARGET/$(basename "$0")"
|
||||
else
|
||||
echo copying aborted. exiting
|
||||
exitp 3
|
||||
fi
|
||||
fi
|
||||
echo running from $EXEDIR
|
||||
}
|
||||
|
||||
|
||||
service_install_systemd()
|
||||
{
|
||||
echo \* installing zapret service
|
||||
|
||||
if [ -w "$SYSTEMD_SYSTEM_DIR" ] ; then
|
||||
rm -f "$INIT_SCRIPT"
|
||||
cp -f "$EXEDIR/init.d/systemd/zapret2.service" "$SYSTEMD_SYSTEM_DIR"
|
||||
"$SYSTEMCTL" daemon-reload
|
||||
"$SYSTEMCTL" enable zapret2 || {
|
||||
echo could not enable systemd service
|
||||
exitp 20
|
||||
}
|
||||
else
|
||||
echo '!!! READONLY SYSTEM DETECTED !!! CANNOT INSTALL SYSTEMD UNITS !!!'
|
||||
fi
|
||||
}
|
||||
|
||||
timer_install_systemd()
|
||||
{
|
||||
echo \* installing zapret2-list-update timer
|
||||
|
||||
if [ -w "$SYSTEMD_SYSTEM_DIR" ] ; then
|
||||
"$SYSTEMCTL" disable zapret2-list-update.timer
|
||||
"$SYSTEMCTL" stop zapret2-list-update.timer
|
||||
cp -f "$EXEDIR/init.d/systemd/zapret2-list-update.service" "$SYSTEMD_SYSTEM_DIR"
|
||||
cp -f "$EXEDIR/init.d/systemd/zapret2-list-update.timer" "$SYSTEMD_SYSTEM_DIR"
|
||||
"$SYSTEMCTL" daemon-reload
|
||||
"$SYSTEMCTL" enable zapret2-list-update.timer || {
|
||||
echo could not enable zapret2-list-update.timer
|
||||
exitp 20
|
||||
}
|
||||
"$SYSTEMCTL" start zapret2-list-update.timer || {
|
||||
echo could not start zapret2-list-update.timer
|
||||
exitp 30
|
||||
}
|
||||
else
|
||||
echo '!!! READONLY SYSTEM DETECTED !!! CANNOT INSTALL SYSTEMD UNITS !!!'
|
||||
fi
|
||||
}
|
||||
|
||||
download_list()
|
||||
{
|
||||
[ -x "$GET_LIST" ] && {
|
||||
echo \* downloading blocked ip/host list
|
||||
|
||||
# can be txt or txt.gz
|
||||
"$IPSET_DIR/clear_lists.sh"
|
||||
"$GET_LIST"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dnstest()
|
||||
{
|
||||
# $1 - dns server. empty for system resolver
|
||||
nslookup w3.org $1 >/dev/null 2>/dev/null
|
||||
}
|
||||
check_dns()
|
||||
{
|
||||
echo \* checking DNS
|
||||
|
||||
dnstest || {
|
||||
echo -- DNS is not working. It's either misconfigured or blocked or you don't have inet access.
|
||||
return 1
|
||||
}
|
||||
echo system DNS is working
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
install_systemd()
|
||||
{
|
||||
INIT_SCRIPT_SRC="$EXEDIR/init.d/sysv/zapret"
|
||||
CUSTOM_DIR="$ZAPRET_RW/init.d/sysv"
|
||||
|
||||
check_bins
|
||||
require_root
|
||||
check_readonly_system
|
||||
check_location copy_all
|
||||
check_dns
|
||||
check_virt
|
||||
service_stop_systemd
|
||||
select_fwtype
|
||||
check_prerequisites_linux
|
||||
install_binaries
|
||||
select_ipv6
|
||||
ask_config_offload
|
||||
ask_config
|
||||
service_install_systemd
|
||||
download_list
|
||||
# in case its left from old version of zapret
|
||||
crontab_del_quiet
|
||||
# now we use systemd timers
|
||||
timer_install_systemd
|
||||
service_start_systemd
|
||||
}
|
||||
|
||||
_install_sysv()
|
||||
{
|
||||
# $1 - install init script
|
||||
|
||||
CUSTOM_DIR="$ZAPRET_RW/init.d/sysv"
|
||||
|
||||
check_bins
|
||||
require_root
|
||||
check_readonly_system
|
||||
check_location copy_all
|
||||
check_dns
|
||||
check_virt
|
||||
service_stop_sysv
|
||||
select_fwtype
|
||||
check_prerequisites_linux
|
||||
install_binaries
|
||||
select_ipv6
|
||||
ask_config_offload
|
||||
ask_config
|
||||
$1
|
||||
download_list
|
||||
crontab_del_quiet
|
||||
# desktop system. more likely up at daytime
|
||||
crontab_add 10 22
|
||||
service_start_sysv
|
||||
}
|
||||
|
||||
install_sysv()
|
||||
{
|
||||
INIT_SCRIPT_SRC="$EXEDIR/init.d/sysv/zapret2"
|
||||
_install_sysv install_sysv_init
|
||||
}
|
||||
|
||||
install_openrc()
|
||||
{
|
||||
INIT_SCRIPT_SRC="$EXEDIR/init.d/openrc/zapret2"
|
||||
_install_sysv install_openrc_init
|
||||
}
|
||||
|
||||
|
||||
install_linux()
|
||||
{
|
||||
INIT_SCRIPT_SRC="$EXEDIR/init.d/sysv/zapret2"
|
||||
CUSTOM_DIR="$ZAPRET_RW/init.d/sysv"
|
||||
|
||||
check_bins
|
||||
require_root
|
||||
check_location copy_all
|
||||
check_dns
|
||||
check_virt
|
||||
select_fwtype
|
||||
check_prerequisites_linux
|
||||
install_binaries
|
||||
select_ipv6
|
||||
ask_config_offload
|
||||
ask_config
|
||||
download_list
|
||||
crontab_del_quiet
|
||||
# desktop system. more likely up at daytime
|
||||
crontab_add 10 22
|
||||
|
||||
echo
|
||||
echo '!!! WARNING. YOUR SETUP IS INCOMPLETE !!!'
|
||||
echo you must manually add to auto start : $INIT_SCRIPT_SRC start
|
||||
echo make sure it\'s executed after your custom/firewall iptables configuration
|
||||
echo "if your system uses sysv init : ln -fs $INIT_SCRIPT_SRC /etc/init.d/zapret ; chkconfig zapret on"
|
||||
}
|
||||
|
||||
|
||||
deoffload_openwrt_firewall()
|
||||
{
|
||||
echo \* checking flow offloading
|
||||
|
||||
[ "$FWTYPE" = "nftables" ] || is_ipt_flow_offload_avail || {
|
||||
echo unavailable
|
||||
return
|
||||
}
|
||||
|
||||
local fo=$(uci -q get firewall.@defaults[0].flow_offloading)
|
||||
|
||||
if [ "$fo" = "1" ] ; then
|
||||
local mod=0
|
||||
printf "system wide flow offloading detected. "
|
||||
case $FLOWOFFLOAD in
|
||||
donttouch)
|
||||
if [ "$NFQWS2_ENABLE" = "1" ]; then
|
||||
echo its incompatible with nfqws tcp data tampering. disabling
|
||||
uci set firewall.@defaults[0].flow_offloading=0
|
||||
mod=1
|
||||
else
|
||||
if dir_is_not_empty "$CUSTOM_DIR/custom.d" ; then
|
||||
echo
|
||||
echo !!! CUSTOM SCRIPTS ARE PRESENT !!! only you can decide whether flow offloading is compatible.
|
||||
echo !!! CUSTOM SCRIPTS ARE PRESENT !!! if they use nfqws they will not work. you have to disable system-wide offloading.
|
||||
else
|
||||
echo its compatible with selected options. not disabling
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo zapret will disable system wide offloading setting and add selective rules if required
|
||||
uci set firewall.@defaults[0].flow_offloading=0
|
||||
mod=1
|
||||
esac
|
||||
[ "$mod" = "1" ] && uci commit firewall
|
||||
else
|
||||
echo system wide software flow offloading disabled. ok
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
install_openwrt()
|
||||
{
|
||||
INIT_SCRIPT_SRC="$EXEDIR/init.d/openwrt/zapret2"
|
||||
CUSTOM_DIR="$ZAPRET_RW/init.d/openwrt"
|
||||
FW_SCRIPT_SRC="$EXEDIR/init.d/openwrt/firewall.zapret2"
|
||||
OPENWRT_FW_INCLUDE=/etc/firewall.zapret2
|
||||
OPENWRT_IFACE_HOOK="$EXEDIR/init.d/openwrt/90-zapret2"
|
||||
|
||||
check_bins
|
||||
require_root
|
||||
check_location copy_openwrt
|
||||
install_binaries
|
||||
check_dns
|
||||
check_virt
|
||||
|
||||
local FWTYPE_OLD=$FWTYPE
|
||||
|
||||
echo \* stopping current firewall rules/daemons
|
||||
"$INIT_SCRIPT_SRC" stop_fw
|
||||
"$INIT_SCRIPT_SRC" stop_daemons
|
||||
|
||||
select_fwtype
|
||||
select_ipv6
|
||||
check_prerequisites_openwrt
|
||||
ask_config
|
||||
ask_config_tmpdir
|
||||
ask_config_offload
|
||||
# stop and reinstall sysv init
|
||||
install_sysv_init
|
||||
[ "$FWTYPE_OLD" != "$FWTYPE" -a "$FWTYPE_OLD" = iptables -a -n "$OPENWRT_FW3" ] && remove_openwrt_firewall
|
||||
# free some RAM
|
||||
clear_ipset
|
||||
download_list
|
||||
crontab_del_quiet
|
||||
# router system : works 24/7. night is the best time
|
||||
crontab_add 0 6
|
||||
cron_ensure_running
|
||||
install_openwrt_iface_hook
|
||||
# in case of nftables or iptables without fw3 sysv init script also controls firewall
|
||||
[ -n "$OPENWRT_FW3" -a "$FWTYPE" = iptables ] && install_openwrt_firewall
|
||||
service_start_sysv
|
||||
deoffload_openwrt_firewall
|
||||
restart_openwrt_firewall
|
||||
}
|
||||
|
||||
|
||||
|
||||
remove_pf_zapret_hooks()
|
||||
{
|
||||
echo \* removing zapret PF hooks
|
||||
|
||||
pf_anchors_clear
|
||||
}
|
||||
|
||||
macos_fw_reload_trigger_clear()
|
||||
{
|
||||
LISTS_RELOAD=
|
||||
write_config_var LISTS_RELOAD
|
||||
}
|
||||
macos_fw_reload_trigger_set()
|
||||
{
|
||||
LISTS_RELOAD="$INIT_SCRIPT_SRC reload-fw-tables"
|
||||
write_config_var LISTS_RELOAD
|
||||
}
|
||||
|
||||
|
||||
|
||||
# build binaries, do not use precompiled
|
||||
[ "$1" = "make" ] && FORCE_BUILD=1
|
||||
|
||||
umask 0022
|
||||
fix_sbin_path
|
||||
fsleep_setup
|
||||
check_system
|
||||
check_source
|
||||
|
||||
case $SYSTEM in
|
||||
systemd)
|
||||
install_systemd
|
||||
;;
|
||||
openrc)
|
||||
install_openrc
|
||||
;;
|
||||
linux)
|
||||
install_linux
|
||||
;;
|
||||
openwrt)
|
||||
install_openwrt
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
exitp 0
|
||||
51
install_prereq.sh
Executable file
51
install_prereq.sh
Executable file
@@ -0,0 +1,51 @@
|
||||
#!/bin/sh
|
||||
|
||||
# install prerequisites
|
||||
|
||||
EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
ZAPRET_BASE=${ZAPRET_BASE:-"$EXEDIR"}
|
||||
ZAPRET_RW=${ZAPRET_RW:-"$ZAPRET_BASE"}
|
||||
ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"}
|
||||
ZAPRET_CONFIG_DEFAULT="$ZAPRET_BASE/config.default"
|
||||
|
||||
[ -f "$ZAPRET_CONFIG" ] || {
|
||||
ZAPRET_CONFIG_DIR="$(dirname "$ZAPRET_CONFIG")"
|
||||
[ -d "$ZAPRET_CONFIG_DIR" ] || mkdir -p "$ZAPRET_CONFIG_DIR"
|
||||
cp "$ZAPRET_CONFIG_DEFAULT" "$ZAPRET_CONFIG"
|
||||
}
|
||||
|
||||
. "$ZAPRET_CONFIG"
|
||||
. "$ZAPRET_BASE/common/base.sh"
|
||||
. "$ZAPRET_BASE/common/elevate.sh"
|
||||
. "$ZAPRET_BASE/common/fwtype.sh"
|
||||
. "$ZAPRET_BASE/common/dialog.sh"
|
||||
. "$ZAPRET_BASE/common/installer.sh"
|
||||
. "$ZAPRET_BASE/common/ipt.sh"
|
||||
|
||||
umask 0022
|
||||
fix_sbin_path
|
||||
fsleep_setup
|
||||
check_system accept_unknown_rc
|
||||
[ $UNAME = "Linux" ] || {
|
||||
echo no prerequisites required for $UNAME
|
||||
exitp 0
|
||||
}
|
||||
require_root
|
||||
|
||||
case $UNAME in
|
||||
Linux)
|
||||
select_fwtype
|
||||
case $SYSTEM in
|
||||
openwrt)
|
||||
select_ipv6
|
||||
check_prerequisites_openwrt
|
||||
;;
|
||||
*)
|
||||
check_prerequisites_linux
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
exitp 0
|
||||
19
ipset/antifilter.helper
Normal file
19
ipset/antifilter.helper
Normal file
@@ -0,0 +1,19 @@
|
||||
get_antifilter()
|
||||
{
|
||||
# $1 - list url
|
||||
# $2 - target file
|
||||
local ZIPLISTTMP="$TMPDIR/zapret-ip.txt"
|
||||
|
||||
[ "$DISABLE_IPV4" != "1" ] && {
|
||||
curl --fail --max-time 150 --connect-timeout 20 --max-filesize 41943040 -k -L "$1" | cut_local >"$ZIPLISTTMP" &&
|
||||
{
|
||||
dlsize=$(LC_ALL=C LANG=C wc -c "$ZIPLISTTMP" | xargs | cut -f 1 -d ' ')
|
||||
if [ $dlsize -lt 102400 ]; then
|
||||
echo list file is too small. can be bad.
|
||||
exit 2
|
||||
fi
|
||||
ip2net4 <"$ZIPLISTTMP" | zz "$2"
|
||||
rm -f "$ZIPLISTTMP"
|
||||
}
|
||||
}
|
||||
}
|
||||
8
ipset/clear_lists.sh
Executable file
8
ipset/clear_lists.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
rm -f "$ZIPLIST"* "$ZIPLIST6"* "$ZIPLIST_USER" "$ZIPLIST_USER6" "$ZIPLIST_IPBAN"* "$ZIPLIST_IPBAN6"* "$ZIPLIST_USER_IPBAN" "$ZIPLIST_USER_IPBAN6" "$ZIPLIST_EXCLUDE" "$ZIPLIST_EXCLUDE6" "$ZHOSTLIST"*
|
||||
308
ipset/create_ipset.sh
Executable file
308
ipset/create_ipset.sh
Executable file
@@ -0,0 +1,308 @@
|
||||
#!/bin/sh
|
||||
|
||||
# create ipset or ipfw table from resolved ip's
|
||||
# $1=no-update - do not update ipset, only create if its absent
|
||||
# $1=clear - clear ipset
|
||||
|
||||
EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
|
||||
. "$EXEDIR/def.sh"
|
||||
. "$ZAPRET_BASE/common/fwtype.sh"
|
||||
. "$ZAPRET_BASE/common/nft.sh"
|
||||
|
||||
IPSET_CMD="$TMPDIR/ipset_cmd.txt"
|
||||
IPSET_SAVERAM_CHUNK_SIZE=20000
|
||||
IPSET_SAVERAM_MIN_FILESIZE=131072
|
||||
|
||||
NFSET_TEMP="$TMPDIR/nfset_temp.txt"
|
||||
NFSET_SAVERAM_MIN_FILESIZE=16384
|
||||
NFSET_SAVERAM_CHUNK_SIZE=1000
|
||||
|
||||
IPSET_HOOK_TEMP="$TMPDIR/ipset_hook.txt"
|
||||
|
||||
while [ -n "$1" ]; do
|
||||
[ "$1" = "no-update" ] && NO_UPDATE=1
|
||||
[ "$1" = "clear" ] && DO_CLEAR=1
|
||||
shift
|
||||
done
|
||||
|
||||
|
||||
file_extract_lines()
|
||||
{
|
||||
# $1 - filename
|
||||
# $2 - from line (starting with 0)
|
||||
# $3 - line count
|
||||
# awk "{ err=1 } NR < $(($2+1)) { next } { print; err=0 } NR == $(($2+$3)) { exit err } END {exit err}" "$1"
|
||||
$AWK "NR < $(($2+1)) { next } { print } NR == $(($2+$3)) { exit }" "$1"
|
||||
}
|
||||
ipset_restore_chunked()
|
||||
{
|
||||
# $1 - filename
|
||||
# $2 - chunk size
|
||||
local pos lines
|
||||
[ -f "$1" ] || return
|
||||
lines=$(wc -l <"$1")
|
||||
pos=$lines
|
||||
while [ "$pos" -gt "0" ]; do
|
||||
pos=$((pos-$2))
|
||||
[ "$pos" -lt "0" ] && pos=0
|
||||
file_extract_lines "$1" $pos $2 | ipset -! restore
|
||||
sed -i "$(($pos+1)),$ d" "$1"
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
ipset_get_script()
|
||||
{
|
||||
# $1 - ipset name
|
||||
sed -nEe "s/^.+$/add $1 &/p"
|
||||
}
|
||||
ipset_get_script_from_file()
|
||||
{
|
||||
# $1 - filename
|
||||
# $2 - ipset name
|
||||
zzcat "$1" | sort -u | ipset_get_script $2
|
||||
}
|
||||
ipset_restore()
|
||||
{
|
||||
# $1 - ipset name
|
||||
# $2 - filename
|
||||
|
||||
zzexist "$2" || return
|
||||
local fsize=$(zzsize "$2")
|
||||
local svram=0
|
||||
# do not saveram small files. file can also be gzipped
|
||||
[ "$SAVERAM" = "1" ] && [ "$fsize" -ge "$IPSET_SAVERAM_MIN_FILESIZE" ] && svram=1
|
||||
|
||||
local T="Adding to ipset $1 "
|
||||
[ "$svram" = "1" ] && T="$T (saveram)"
|
||||
T="$T : $f"
|
||||
echo $T
|
||||
|
||||
if [ "$svram" = "1" ]; then
|
||||
ipset_get_script_from_file "$2" "$1" >"$IPSET_CMD"
|
||||
ipset_restore_chunked "$IPSET_CMD" $IPSET_SAVERAM_CHUNK_SIZE
|
||||
rm -f "$IPSET_CMD"
|
||||
else
|
||||
ipset_get_script_from_file "$2" "$1" | ipset -! restore
|
||||
fi
|
||||
}
|
||||
create_ipset()
|
||||
{
|
||||
if [ "$1" -eq "6" ]; then
|
||||
FAMILY=inet6
|
||||
else
|
||||
FAMILY=inet
|
||||
fi
|
||||
ipset create $2 $3 $4 family $FAMILY 2>/dev/null || {
|
||||
[ "$NO_UPDATE" = "1" ] && return 0
|
||||
}
|
||||
ipset flush $2
|
||||
[ "$DO_CLEAR" = "1" ] || {
|
||||
for f in "$5" "$6" ; do
|
||||
ipset_restore "$2" "$f"
|
||||
done
|
||||
[ -n "$IPSET_HOOK" ] && $IPSET_HOOK $2 | ipset_get_script $2 | ipset -! restore
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
nfset_get_script_multi()
|
||||
{
|
||||
# $1 - set name
|
||||
# $2,$3,... - filenames
|
||||
|
||||
# all in one shot. this allows to merge overlapping ranges
|
||||
# good but eats lots of RAM
|
||||
|
||||
local set=$1 nonempty N=1 f
|
||||
|
||||
shift
|
||||
# first we need to make sure at least one element exists or nft will fail
|
||||
while :
|
||||
do
|
||||
eval f=\$$N
|
||||
[ -n "$f" ] || break
|
||||
nonempty=$(zzexist "$f" && zzcat "$f" 2>/dev/null | head -n 1)
|
||||
[ -n "$nonempty" ] && break
|
||||
N=$(($N+1))
|
||||
done
|
||||
|
||||
[ -n "$nonempty" ] && {
|
||||
echo "add element inet $ZAPRET_NFT_TABLE $set {"
|
||||
while [ -n "$1" ]; do
|
||||
zzexist "$1" && zzcat "$1" | sed -nEe "s/^.+$/&,/p"
|
||||
shift
|
||||
done
|
||||
echo "}"
|
||||
}
|
||||
}
|
||||
nfset_restore()
|
||||
{
|
||||
# $1 - set name
|
||||
# $2,$3,... - filenames
|
||||
|
||||
echo "Adding to nfset $1 : $2 $3 $4 $5"
|
||||
local hookfile
|
||||
[ -n "$IPSET_HOOK" ] && {
|
||||
$IPSET_HOOK $1 >"$IPSET_HOOK_TEMP"
|
||||
[ -s "$IPSET_HOOK_TEMP" ] && hookfile=$IPSET_HOOK_TEMP
|
||||
}
|
||||
nfset_get_script_multi "$@" $hookfile | nft -f -
|
||||
rm -f "$IPSET_HOOK_TEMP"
|
||||
}
|
||||
create_nfset()
|
||||
{
|
||||
# $1 - family
|
||||
# $2 - set name
|
||||
# $3 - maxelem
|
||||
# $4,$5 - list files
|
||||
|
||||
local policy
|
||||
[ $SAVERAM = "1" ] && policy="policy memory;"
|
||||
nft_create_set $2 "type ipv${1}_addr; size $3; flags interval; auto-merge; $policy" || {
|
||||
[ "$NO_UPDATE" = "1" ] && return 0
|
||||
nft flush set inet $ZAPRET_NFT_TABLE $2
|
||||
}
|
||||
[ "$DO_CLEAR" = "1" ] || {
|
||||
nfset_restore $2 $4 $5
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
add_ipfw_table()
|
||||
{
|
||||
# $1 - table name
|
||||
sed -nEe "s/^.+$/table $1 add &/p" | ipfw -q /dev/stdin
|
||||
}
|
||||
populate_ipfw_table()
|
||||
{
|
||||
# $1 - table name
|
||||
# $2 - ip list file
|
||||
zzexist "$2" || return
|
||||
zzcat "$2" | sort -u | add_ipfw_table $1
|
||||
}
|
||||
create_ipfw_table()
|
||||
{
|
||||
# $1 - table name
|
||||
# $2 - table options
|
||||
# $3,$4, ... - ip list files. can be v4,v6 or mixed
|
||||
|
||||
local name=$1
|
||||
ipfw table "$name" create $2 2>/dev/null || {
|
||||
[ "$NO_UPDATE" = "1" ] && return 0
|
||||
}
|
||||
ipfw -q table $1 flush
|
||||
shift
|
||||
shift
|
||||
[ "$DO_CLEAR" = "1" ] || {
|
||||
while [ -n "$1" ]; do
|
||||
echo "Adding to ipfw table $name : $1"
|
||||
populate_ipfw_table $name "$1"
|
||||
shift
|
||||
done
|
||||
[ -n "$IPSET_HOOK" ] && $IPSET_HOOK $name | add_ipfw_table $name
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
print_reloading_backend()
|
||||
{
|
||||
# $1 - backend name
|
||||
local s="reloading $1 backend"
|
||||
if [ "$NO_UPDATE" = 1 ]; then
|
||||
s="$s (no-update)"
|
||||
elif [ "$DO_CLEAR" = 1 ]; then
|
||||
s="$s (clear)"
|
||||
else
|
||||
s="$s (forced-update)"
|
||||
fi
|
||||
echo $s
|
||||
}
|
||||
|
||||
|
||||
oom_adjust_high
|
||||
get_fwtype
|
||||
|
||||
if [ -n "$LISTS_RELOAD" ] ; then
|
||||
if [ "$LISTS_RELOAD" = "-" ] ; then
|
||||
echo not reloading ip list backend
|
||||
true
|
||||
else
|
||||
echo executing custom ip list reload command : $LISTS_RELOAD
|
||||
$LISTS_RELOAD
|
||||
[ -n "$IPSET_HOOK" ] && $IPSET_HOOK
|
||||
fi
|
||||
else
|
||||
case "$FWTYPE" in
|
||||
iptables)
|
||||
# ipset seem to buffer the whole script to memory
|
||||
# on low RAM system this can cause oom errors
|
||||
# in SAVERAM mode we feed script lines in portions starting from the end, while truncating source file to free /tmp space
|
||||
# only /tmp is considered tmpfs. other locations mean tmpdir was redirected to a disk
|
||||
SAVERAM=0
|
||||
[ "$TMPDIR" = "/tmp" ] && {
|
||||
RAMSIZE=$($GREP MemTotal /proc/meminfo | $AWK '{print $2}')
|
||||
[ "$RAMSIZE" -lt "110000" ] && SAVERAM=1
|
||||
}
|
||||
print_reloading_backend ipset
|
||||
[ "$DISABLE_IPV4" != "1" ] && {
|
||||
create_ipset 4 $ZIPSET hash:net "$IPSET_OPT" "$ZIPLIST" "$ZIPLIST_USER"
|
||||
create_ipset 4 $ZIPSET_IPBAN hash:net "$IPSET_OPT" "$ZIPLIST_IPBAN" "$ZIPLIST_USER_IPBAN"
|
||||
create_ipset 4 $ZIPSET_EXCLUDE hash:net "$IPSET_OPT_EXCLUDE" "$ZIPLIST_EXCLUDE"
|
||||
}
|
||||
[ "$DISABLE_IPV6" != "1" ] && {
|
||||
create_ipset 6 $ZIPSET6 hash:net "$IPSET_OPT" "$ZIPLIST6" "$ZIPLIST_USER6"
|
||||
create_ipset 6 $ZIPSET_IPBAN6 hash:net "$IPSET_OPT" "$ZIPLIST_IPBAN6" "$ZIPLIST_USER_IPBAN6"
|
||||
create_ipset 6 $ZIPSET_EXCLUDE6 hash:net "$IPSET_OPT_EXCLUDE" "$ZIPLIST_EXCLUDE6"
|
||||
}
|
||||
true
|
||||
;;
|
||||
nftables)
|
||||
nft_create_table && {
|
||||
SAVERAM=0
|
||||
RAMSIZE=$($GREP MemTotal /proc/meminfo | $AWK '{print $2}')
|
||||
[ "$RAMSIZE" -lt "420000" ] && SAVERAM=1
|
||||
print_reloading_backend "nftables set"
|
||||
[ "$DISABLE_IPV4" != "1" ] && {
|
||||
create_nfset 4 $ZIPSET $SET_MAXELEM "$ZIPLIST" "$ZIPLIST_USER"
|
||||
create_nfset 4 $ZIPSET_IPBAN $SET_MAXELEM "$ZIPLIST_IPBAN" "$ZIPLIST_USER_IPBAN"
|
||||
create_nfset 4 $ZIPSET_EXCLUDE $SET_MAXELEM_EXCLUDE "$ZIPLIST_EXCLUDE"
|
||||
}
|
||||
[ "$DISABLE_IPV6" != "1" ] && {
|
||||
create_nfset 6 $ZIPSET6 $SET_MAXELEM "$ZIPLIST6" "$ZIPLIST_USER6"
|
||||
create_nfset 6 $ZIPSET_IPBAN6 $SET_MAXELEM "$ZIPLIST_IPBAN6" "$ZIPLIST_USER_IPBAN6"
|
||||
create_nfset 6 $ZIPSET_EXCLUDE6 $SET_MAXELEM_EXCLUDE "$ZIPLIST_EXCLUDE6"
|
||||
}
|
||||
true
|
||||
}
|
||||
;;
|
||||
ipfw)
|
||||
print_reloading_backend "ipfw table"
|
||||
if [ "$DISABLE_IPV4" != "1" ] && [ "$DISABLE_IPV6" != "1" ]; then
|
||||
create_ipfw_table $ZIPSET "$IPFW_TABLE_OPT" "$ZIPLIST" "$ZIPLIST_USER" "$ZIPLIST6" "$ZIPLIST_USER6"
|
||||
create_ipfw_table $ZIPSET_IPBAN "$IPFW_TABLE_OPT" "$ZIPLIST_IPBAN" "$ZIPLIST_USER_IPBAN" "$ZIPLIST_IPBAN6" "$ZIPLIST_USER_IPBAN6"
|
||||
create_ipfw_table $ZIPSET_EXCLUDE "$IPFW_TABLE_OPT_EXCLUDE" "$ZIPLIST_EXCLUDE" "$ZIPLIST_EXCLUDE6"
|
||||
elif [ "$DISABLE_IPV4" != "1" ]; then
|
||||
create_ipfw_table $ZIPSET "$IPFW_TABLE_OPT" "$ZIPLIST" "$ZIPLIST_USER"
|
||||
create_ipfw_table $ZIPSET_IPBAN "$IPFW_TABLE_OPT" "$ZIPLIST_IPBAN" "$ZIPLIST_USER_IPBAN"
|
||||
create_ipfw_table $ZIPSET_EXCLUDE "$IPFW_TABLE_OPT_EXCLUDE" "$ZIPLIST_EXCLUDE"
|
||||
elif [ "$DISABLE_IPV6" != "1" ]; then
|
||||
create_ipfw_table $ZIPSET "$IPFW_TABLE_OPT" "$ZIPLIST6" "$ZIPLIST_USER6"
|
||||
create_ipfw_table $ZIPSET_IPBAN "$IPFW_TABLE_OPT" "$ZIPLIST_IPBAN6" "$ZIPLIST_USER_IPBAN6"
|
||||
create_ipfw_table $ZIPSET_EXCLUDE "$IPFW_TABLE_OPT_EXCLUDE" "$ZIPLIST_EXCLUDE6"
|
||||
else
|
||||
create_ipfw_table $ZIPSET "$IPFW_TABLE_OPT"
|
||||
create_ipfw_table $ZIPSET_IPBAN "$IPFW_TABLE_OPT"
|
||||
create_ipfw_table $ZIPSET_EXCLUDE "$IPFW_TABLE_OPT_EXCLUDE"
|
||||
fi
|
||||
true
|
||||
;;
|
||||
*)
|
||||
echo no supported ip list backend found
|
||||
true
|
||||
;;
|
||||
esac
|
||||
|
||||
fi
|
||||
283
ipset/def.sh
Normal file
283
ipset/def.sh
Normal file
@@ -0,0 +1,283 @@
|
||||
EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
ZAPRET_BASE=${ZAPRET_BASE:-"$(cd "$EXEDIR/.."; pwd)"}
|
||||
ZAPRET_RW=${ZAPRET_RW:-"$ZAPRET_BASE"}
|
||||
ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"}
|
||||
IPSET_RW_DIR="$ZAPRET_RW/ipset"
|
||||
|
||||
[ -f "$ZAPRET_CONFIG" ] && . "$ZAPRET_CONFIG"
|
||||
. "$ZAPRET_BASE/common/base.sh"
|
||||
|
||||
[ -z "$TMPDIR" ] && TMPDIR=/tmp
|
||||
[ -z "$GZIP_LISTS" ] && GZIP_LISTS=1
|
||||
|
||||
[ -z "$SET_MAXELEM" ] && SET_MAXELEM=262144
|
||||
[ -z "$IPSET_OPT" ] && IPSET_OPT="hashsize 262144 maxelem $SET_MAXELEM"
|
||||
[ -z "$SET_MAXELEM_EXCLUDE" ] && SET_MAXELEM_EXCLUDE=65536
|
||||
[ -z "$IPSET_OPT_EXCLUDE" ] && IPSET_OPT_EXCLUDE="hashsize 1024 maxelem $SET_MAXELEM_EXCLUDE"
|
||||
|
||||
[ -z "$IPFW_TABLE_OPT" ] && IPFW_TABLE_OPT="algo addr:radix"
|
||||
[ -z "$IPFW_TABLE_OPT_EXCLUDE" ] && IPFW_TABLE_OPT_EXCLUDE="algo addr:radix"
|
||||
|
||||
ZIPSET=zapret
|
||||
ZIPSET6=zapret6
|
||||
ZIPSET_EXCLUDE=nozapret
|
||||
ZIPSET_EXCLUDE6=nozapret6
|
||||
ZIPLIST="$IPSET_RW_DIR/zapret-ip.txt"
|
||||
ZIPLIST6="$IPSET_RW_DIR/zapret-ip6.txt"
|
||||
ZIPLIST_EXCLUDE="$IPSET_RW_DIR/zapret-ip-exclude.txt"
|
||||
ZIPLIST_EXCLUDE6="$IPSET_RW_DIR/zapret-ip-exclude6.txt"
|
||||
ZIPLIST_USER="$IPSET_RW_DIR/zapret-ip-user.txt"
|
||||
ZIPLIST_USER6="$IPSET_RW_DIR/zapret-ip-user6.txt"
|
||||
ZUSERLIST="$IPSET_RW_DIR/zapret-hosts-user.txt"
|
||||
ZHOSTLIST="$IPSET_RW_DIR/zapret-hosts.txt"
|
||||
|
||||
ZIPSET_IPBAN=ipban
|
||||
ZIPSET_IPBAN6=ipban6
|
||||
ZIPLIST_IPBAN="$IPSET_RW_DIR/zapret-ip-ipban.txt"
|
||||
ZIPLIST_IPBAN6="$IPSET_RW_DIR/zapret-ip-ipban6.txt"
|
||||
ZIPLIST_USER_IPBAN="$IPSET_RW_DIR/zapret-ip-user-ipban.txt"
|
||||
ZIPLIST_USER_IPBAN6="$IPSET_RW_DIR/zapret-ip-user-ipban6.txt"
|
||||
ZUSERLIST_IPBAN="$IPSET_RW_DIR/zapret-hosts-user-ipban.txt"
|
||||
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
|
||||
|
||||
|
||||
|
||||
# BSD grep is damn slow with -f option. prefer GNU grep (ggrep) if present
|
||||
# MacoS in cron does not include /usr/local/bin to PATH
|
||||
if [ -x /usr/local/bin/ggrep ] ; then
|
||||
GREP=/usr/local/bin/ggrep
|
||||
elif [ -x /usr/local/bin/grep ] ; then
|
||||
GREP=/usr/local/bin/grep
|
||||
elif exists ggrep; then
|
||||
GREP=$(whichq ggrep)
|
||||
else
|
||||
GREP=$(whichq grep)
|
||||
fi
|
||||
|
||||
# GNU awk is faster
|
||||
if exists gawk; then
|
||||
AWK=gawk
|
||||
else
|
||||
AWK=awk
|
||||
fi
|
||||
|
||||
grep_supports_b()
|
||||
{
|
||||
# \b does not work with BSD grep
|
||||
$GREP --version 2>&1 | $GREP -qE "BusyBox|GNU"
|
||||
}
|
||||
get_ip_regex()
|
||||
{
|
||||
REG_IPV4='((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\/([0-9]|[12][0-9]|3[012]))?'
|
||||
REG_IPV6='[0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}|:)+(\/([0-9][0-9]?|1[01][0-9]|12[0-8]))?'
|
||||
# good but too slow
|
||||
# REG_IPV6='([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}(/[0-9]+)?|([0-9a-fA-F]{1,4}:){1,7}:(/[0-9]+)?|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}(/[0-9]+)?|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}(/[0-9]+)?|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}(/[0-9]+)?|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}(/[0-9]+)?|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}(/[0-9]+)?|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})(/[0-9]+)?|:((:[0-9a-fA-F]{1,4}){1,7}|:)(/([0-9][0-9]?|1[01][0-9]|12[0-8]))?'
|
||||
# grep_supports_b && {
|
||||
# REG_IPV4="\b$REG_IPV4\b"
|
||||
# REG_IPV6="\b$REG_IPV6\b"
|
||||
# }
|
||||
}
|
||||
|
||||
ip2net4()
|
||||
{
|
||||
if [ -x "$IP2NET" ]; then
|
||||
"$IP2NET" -4 $IP2NET_OPT4
|
||||
else
|
||||
sort -u
|
||||
fi
|
||||
}
|
||||
ip2net6()
|
||||
{
|
||||
if [ -x "$IP2NET" ]; then
|
||||
"$IP2NET" -6 $IP2NET_OPT6
|
||||
else
|
||||
sort -u
|
||||
fi
|
||||
}
|
||||
|
||||
zzexist()
|
||||
{
|
||||
[ -f "$1.gz" ] || [ -f "$1" ]
|
||||
}
|
||||
zztest()
|
||||
{
|
||||
gzip -t "$1" 2>/dev/null
|
||||
}
|
||||
zzcat()
|
||||
{
|
||||
if [ -f "$1.gz" ]; then
|
||||
gunzip -c "$1.gz"
|
||||
elif [ -f "$1" ]; then
|
||||
if zztest "$1"; then
|
||||
gunzip -c "$1"
|
||||
else
|
||||
cat "$1"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
zz()
|
||||
{
|
||||
if [ "$GZIP_LISTS" = "1" ]; then
|
||||
gzip -c >"$1.gz"
|
||||
rm -f "$1"
|
||||
else
|
||||
cat >"$1"
|
||||
rm -f "$1.gz"
|
||||
fi
|
||||
}
|
||||
zzsize()
|
||||
{
|
||||
local f="$1"
|
||||
[ -f "$1.gz" ] && f="$1.gz"
|
||||
if [ -f "$f" ]; then
|
||||
wc -c <"$f" | xargs
|
||||
else
|
||||
printf 0
|
||||
fi
|
||||
}
|
||||
zzcopy()
|
||||
{
|
||||
local is_gz=0
|
||||
zztest "$1" && is_gz=1
|
||||
if [ "$GZIP_LISTS" = 1 -a $is_gz = 1 ]; then
|
||||
cp "$1" "${2}.gz"
|
||||
elif [ "$GZIP_LISTS" != 1 -a $is_gz != 1 ]; then
|
||||
cp "$1" "$2"
|
||||
else
|
||||
zzcat "$1" | zz "$2"
|
||||
fi
|
||||
}
|
||||
|
||||
digger()
|
||||
{
|
||||
# $1 - family (4|6)
|
||||
# $2 - s=enable mdig stats
|
||||
if [ -x "$MDIG" ]; then
|
||||
local cmd
|
||||
[ "$2" = "s" ] && cmd=--stats=1000
|
||||
"$MDIG" --family=$1 --threads=$MDIG_THREADS $cmd
|
||||
else
|
||||
local A=A
|
||||
[ "$1" = "6" ] && A=AAAA
|
||||
dig $A +short +time=8 +tries=2 -f - | $GREP -E '^[^;].*[^\.]$'
|
||||
fi
|
||||
}
|
||||
filedigger()
|
||||
{
|
||||
# $1 - hostlist
|
||||
# $2 - family (4|6)
|
||||
>&2 echo digging $(wc -l <"$1" | xargs) ipv$2 domains : "$1"
|
||||
zzcat "$1" | digger $2 s
|
||||
}
|
||||
flush_dns_cache()
|
||||
{
|
||||
echo clearing all known DNS caches
|
||||
|
||||
if exists killall; then
|
||||
killall -HUP dnsmasq 2>/dev/null
|
||||
# MacOS
|
||||
killall -HUP mDNSResponder 2>/dev/null
|
||||
elif exists pkill; then
|
||||
pkill -HUP ^dnsmasq$
|
||||
else
|
||||
echo no mass killer available ! cant flush dnsmasq
|
||||
fi
|
||||
|
||||
if exists rndc; then
|
||||
rndc flush
|
||||
fi
|
||||
|
||||
if exists systemd-resolve; then
|
||||
systemd-resolve --flush-caches
|
||||
fi
|
||||
|
||||
}
|
||||
dnstest()
|
||||
{
|
||||
local ip="$(echo w3.org | digger 46)"
|
||||
[ -n "$ip" ]
|
||||
}
|
||||
dnstest_with_cache_clear()
|
||||
{
|
||||
flush_dns_cache
|
||||
if dnstest ; then
|
||||
echo DNS is working
|
||||
return 0
|
||||
else
|
||||
echo "! DNS is not working"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
cut_local()
|
||||
{
|
||||
$GREP -vE '^192\.168\.|^127\.|^10\.'
|
||||
}
|
||||
cut_local6()
|
||||
{
|
||||
$GREP -vE '^::|^fc..:|^fd..:|^fe8.:|^fe9.:|^fea.:|^feb.:|^FC..:|^FD..:|^FE8.:|^FE9.:|^FEA.:|^FEB.:'
|
||||
}
|
||||
|
||||
oom_adjust_high()
|
||||
{
|
||||
[ -f /proc/$$/oom_score_adj ] && {
|
||||
echo setting high oom kill priority
|
||||
echo -n 100 >/proc/$$/oom_score_adj
|
||||
}
|
||||
}
|
||||
|
||||
getexclude()
|
||||
{
|
||||
oom_adjust_high
|
||||
dnstest_with_cache_clear || return
|
||||
[ -f "$ZUSERLIST_EXCLUDE" ] && {
|
||||
[ "$DISABLE_IPV4" != "1" ] && filedigger "$ZUSERLIST_EXCLUDE" 4 | sort -u > "$ZIPLIST_EXCLUDE"
|
||||
[ "$DISABLE_IPV6" != "1" ] && filedigger "$ZUSERLIST_EXCLUDE" 6 | sort -u > "$ZIPLIST_EXCLUDE6"
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
_get_ipban()
|
||||
{
|
||||
[ -f "$ZUSERLIST_IPBAN" ] && {
|
||||
[ "$DISABLE_IPV4" != "1" ] && filedigger "$ZUSERLIST_IPBAN" 4 | cut_local | sort -u > "$ZIPLIST_USER_IPBAN"
|
||||
[ "$DISABLE_IPV6" != "1" ] && filedigger "$ZUSERLIST_IPBAN" 6 | cut_local6 | sort -u > "$ZIPLIST_USER_IPBAN6"
|
||||
}
|
||||
}
|
||||
getuser()
|
||||
{
|
||||
getexclude || return
|
||||
[ -f "$ZUSERLIST" ] && {
|
||||
[ "$DISABLE_IPV4" != "1" ] && filedigger "$ZUSERLIST" 4 | cut_local | sort -u > "$ZIPLIST_USER"
|
||||
[ "$DISABLE_IPV6" != "1" ] && filedigger "$ZUSERLIST" 6 | cut_local6 | sort -u > "$ZIPLIST_USER6"
|
||||
}
|
||||
_get_ipban
|
||||
return 0
|
||||
}
|
||||
getipban()
|
||||
{
|
||||
getexclude || return
|
||||
_get_ipban
|
||||
return 0
|
||||
}
|
||||
|
||||
hup_zapret_daemons()
|
||||
{
|
||||
echo forcing zapret daemons to reload their hostlist
|
||||
if exists killall; then
|
||||
killall -HUP tpws nfqws dvtws 2>/dev/null
|
||||
elif exists pkill; then
|
||||
pkill -HUP ^tpws$
|
||||
pkill -HUP ^nfqws$
|
||||
pkill -HUP ^dvtws$
|
||||
else
|
||||
echo no mass killer available ! cant HUP zapret daemons
|
||||
fi
|
||||
}
|
||||
13
ipset/get_antifilter_allyouneed.sh
Executable file
13
ipset/get_antifilter_allyouneed.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
getuser && {
|
||||
. "$IPSET_DIR/antifilter.helper"
|
||||
get_antifilter https://antifilter.download/list/allyouneed.lst "$ZIPLIST"
|
||||
}
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
13
ipset/get_antifilter_ip.sh
Executable file
13
ipset/get_antifilter_ip.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
getuser && {
|
||||
. "$IPSET_DIR/antifilter.helper"
|
||||
get_antifilter https://antifilter.download/list/ip.lst "$ZIPLIST"
|
||||
}
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
13
ipset/get_antifilter_ipresolve.sh
Executable file
13
ipset/get_antifilter_ipresolve.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
getuser && {
|
||||
. "$IPSET_DIR/antifilter.helper"
|
||||
get_antifilter https://antifilter.download/list/ipresolve.lst "$ZIPLIST"
|
||||
}
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
13
ipset/get_antifilter_ipsmart.sh
Executable file
13
ipset/get_antifilter_ipsmart.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
getuser && {
|
||||
. "$IPSET_DIR/antifilter.helper"
|
||||
get_antifilter https://antifilter.network/download/ipsmart.lst "$ZIPLIST"
|
||||
}
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
13
ipset/get_antifilter_ipsum.sh
Executable file
13
ipset/get_antifilter_ipsum.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
getuser && {
|
||||
. "$IPSET_DIR/antifilter.helper"
|
||||
get_antifilter https://antifilter.download/list/ipsum.lst "$ZIPLIST"
|
||||
}
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
36
ipset/get_antizapret_domains.sh
Executable file
36
ipset/get_antizapret_domains.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
# useful in case ipban set is used in custom scripts
|
||||
FAIL=
|
||||
getipban || FAIL=1
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
[ -n "$FAIL" ] && exit
|
||||
|
||||
ZURL=https://antizapret.prostovpn.org:8443/domains-export.txt
|
||||
ZDOM="$TMPDIR/zapret.txt"
|
||||
|
||||
|
||||
curl -H "Accept-Encoding: gzip" -k --fail --max-time 600 --connect-timeout 5 --retry 3 --max-filesize 251658240 "$ZURL" | gunzip - >"$ZDOM" ||
|
||||
{
|
||||
echo domain list download failed
|
||||
exit 2
|
||||
}
|
||||
|
||||
dlsize=$(LC_ALL=C LANG=C wc -c "$ZDOM" | xargs | cut -f 1 -d ' ')
|
||||
if test $dlsize -lt 102400; then
|
||||
echo list file is too small. can be bad.
|
||||
exit 2
|
||||
fi
|
||||
|
||||
sort -u "$ZDOM" | zz "$ZHOSTLIST"
|
||||
|
||||
rm -f "$ZDOM"
|
||||
|
||||
hup_zapret_daemons
|
||||
|
||||
exit 0
|
||||
10
ipset/get_config.sh
Executable file
10
ipset/get_config.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
# run script specified in config
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
[ -f "$IPSET_DIR/../config" ] && . "$IPSET_DIR/../config"
|
||||
|
||||
[ -z "$GETLIST" ] && GETLIST=get_ipban.sh
|
||||
[ -x "$IPSET_DIR/$GETLIST" ] && exec "$IPSET_DIR/$GETLIST"
|
||||
11
ipset/get_exclude.sh
Executable file
11
ipset/get_exclude.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
# resolve user host list
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
getexclude
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
11
ipset/get_ipban.sh
Executable file
11
ipset/get_ipban.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
# resolve only ipban user host list
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
getipban
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
47
ipset/get_reestr_preresolved.sh
Executable file
47
ipset/get_reestr_preresolved.sh
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
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"
|
||||
|
||||
dl()
|
||||
{
|
||||
# $1 - url
|
||||
# $2 - file
|
||||
# $3 - minsize
|
||||
# $4 - maxsize
|
||||
curl -H "Accept-Encoding: gzip" -k --fail --max-time 120 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$TMPLIST" "$1" ||
|
||||
{
|
||||
echo list download failed : $1
|
||||
exit 2
|
||||
}
|
||||
dlsize=$(LC_ALL=C LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ')
|
||||
if test $dlsize -lt $3; then
|
||||
echo list is too small : $dlsize bytes. can be bad.
|
||||
exit 2
|
||||
fi
|
||||
zzcopy "$TMPLIST" "$2"
|
||||
rm -f "$TMPLIST"
|
||||
}
|
||||
|
||||
getuser && {
|
||||
[ "$DISABLE_IPV4" != "1" ] && {
|
||||
dl "$URL4" "$ZIPLIST" 4096 4194304
|
||||
# dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576
|
||||
}
|
||||
[ "$DISABLE_IPV6" != "1" ] && {
|
||||
dl "$URL6" "$ZIPLIST6" 2048 4194304
|
||||
# dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576
|
||||
}
|
||||
}
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
47
ipset/get_reestr_preresolved_smart.sh
Executable file
47
ipset/get_reestr_preresolved_smart.sh
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
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"
|
||||
|
||||
dl()
|
||||
{
|
||||
# $1 - url
|
||||
# $2 - file
|
||||
# $3 - minsize
|
||||
# $4 - maxsize
|
||||
curl -H "Accept-Encoding: gzip" -k --fail --max-time 120 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$TMPLIST" "$1" ||
|
||||
{
|
||||
echo list download failed : $1
|
||||
exit 2
|
||||
}
|
||||
dlsize=$(LC_ALL=C LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ')
|
||||
if test $dlsize -lt $3; then
|
||||
echo list is too small : $dlsize bytes. can be bad.
|
||||
exit 2
|
||||
fi
|
||||
zzcopy "$TMPLIST" "$2"
|
||||
rm -f "$TMPLIST"
|
||||
}
|
||||
|
||||
getuser && {
|
||||
[ "$DISABLE_IPV4" != "1" ] && {
|
||||
dl "$URL4" "$ZIPLIST" 4096 4194304
|
||||
# dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576
|
||||
}
|
||||
[ "$DISABLE_IPV6" != "1" ] && {
|
||||
dl "$URL6" "$ZIPLIST6" 2048 4194304
|
||||
# dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576
|
||||
}
|
||||
}
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
45
ipset/get_reestr_resolvable_domains.sh
Executable file
45
ipset/get_reestr_resolvable_domains.sh
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
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"
|
||||
|
||||
dl()
|
||||
{
|
||||
# $1 - url
|
||||
# $2 - file
|
||||
# $3 - minsize
|
||||
# $4 - maxsize
|
||||
curl -H "Accept-Encoding: gzip" -k --fail --max-time 120 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$TMPLIST" "$1" ||
|
||||
{
|
||||
echo list download failed : $1
|
||||
exit 2
|
||||
}
|
||||
dlsize=$(LC_ALL=C LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ')
|
||||
if test $dlsize -lt $3; then
|
||||
echo list is too small : $dlsize bytes. can be bad.
|
||||
exit 2
|
||||
fi
|
||||
zzcopy "$TMPLIST" "$2"
|
||||
rm -f "$TMPLIST"
|
||||
}
|
||||
|
||||
dl "$URL" "$ZHOSTLIST" 65536 67108864
|
||||
|
||||
hup_zapret_daemons
|
||||
|
||||
#[ "$DISABLE_IPV4" != "1" ] && dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576
|
||||
#[ "$DISABLE_IPV6" != "1" ] && dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576
|
||||
|
||||
getipban
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
|
||||
exit 0
|
||||
42
ipset/get_refilter_domains.sh
Executable file
42
ipset/get_refilter_domains.sh
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
TMPLIST="$TMPDIR/list.txt"
|
||||
|
||||
URL="https://github.com/1andrevich/Re-filter-lists/releases/latest/download/domains_all.lst"
|
||||
|
||||
dl()
|
||||
{
|
||||
# $1 - url
|
||||
# $2 - file
|
||||
# $3 - minsize
|
||||
# $4 - maxsize
|
||||
curl -L -H "Accept-Encoding: gzip" -k --fail --max-time 60 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$TMPLIST" "$1" ||
|
||||
{
|
||||
echo list download failed : $1
|
||||
exit 2
|
||||
}
|
||||
dlsize=$(LC_ALL=C LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ')
|
||||
if test $dlsize -lt $3; then
|
||||
echo list is too small : $dlsize bytes. can be bad.
|
||||
exit 2
|
||||
fi
|
||||
zzcopy "$TMPLIST" "$2"
|
||||
rm -f "$TMPLIST"
|
||||
}
|
||||
|
||||
# useful in case ipban set is used in custom scripts
|
||||
FAIL=
|
||||
getipban || FAIL=1
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
[ -n "$FAIL" ] && exit
|
||||
|
||||
dl "$URL" "$ZHOSTLIST" 32768 4194304
|
||||
|
||||
hup_zapret_daemons
|
||||
|
||||
exit 0
|
||||
38
ipset/get_refilter_ipsum.sh
Executable file
38
ipset/get_refilter_ipsum.sh
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
TMPLIST="$TMPDIR/list.txt"
|
||||
|
||||
URL="https://github.com/1andrevich/Re-filter-lists/releases/latest/download/ipsum.lst"
|
||||
|
||||
dl()
|
||||
{
|
||||
# $1 - url
|
||||
# $2 - file
|
||||
# $3 - minsize
|
||||
# $4 - maxsize
|
||||
curl -L -H "Accept-Encoding: gzip" -k --fail --max-time 60 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$TMPLIST" "$1" ||
|
||||
{
|
||||
echo list download failed : $1
|
||||
exit 2
|
||||
}
|
||||
dlsize=$(LC_ALL=C LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ')
|
||||
if test $dlsize -lt $3; then
|
||||
echo list is too small : $dlsize bytes. can be bad.
|
||||
exit 2
|
||||
fi
|
||||
zzcopy "$TMPLIST" "$2"
|
||||
rm -f "$TMPLIST"
|
||||
}
|
||||
|
||||
getuser && {
|
||||
[ "$DISABLE_IPV4" != "1" ] && {
|
||||
dl "$URL" "$ZIPLIST" 32768 4194304
|
||||
}
|
||||
}
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
11
ipset/get_user.sh
Executable file
11
ipset/get_user.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
# resolve user host list
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
getuser
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
9
ipset/zapret-hosts-user-exclude.txt.default
Normal file
9
ipset/zapret-hosts-user-exclude.txt.default
Normal file
@@ -0,0 +1,9 @@
|
||||
127.0.0.0/8
|
||||
10.0.0.0/8
|
||||
172.16.0.0/12
|
||||
192.168.0.0/16
|
||||
169.254.0.0/16
|
||||
100.64.0.0/10
|
||||
::1
|
||||
fc00::/7
|
||||
fe80::/10
|
||||
@@ -113,7 +113,7 @@ end
|
||||
-- standard args : direction
|
||||
function http_domcase(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -139,7 +139,7 @@ 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(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -164,7 +164,7 @@ end
|
||||
-- standard args : direction
|
||||
function http_methodeol(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -221,10 +221,10 @@ function synack_split(ctx, desync)
|
||||
error("synack_split: bad mode '"..mode.."'")
|
||||
end
|
||||
else
|
||||
instance_cutoff(ctx) -- mission complete
|
||||
instance_cutoff_shim(ctx, desync) -- mission complete
|
||||
end
|
||||
else
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -238,10 +238,10 @@ function synack(ctx, desync)
|
||||
DLOG("synack: sending")
|
||||
rawsend_dissect_ipfrag(dis, desync_opts(desync))
|
||||
else
|
||||
instance_cutoff(ctx) -- mission complete
|
||||
instance_cutoff_shim(ctx, desync) -- mission complete
|
||||
end
|
||||
else
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -256,10 +256,10 @@ function wsize(ctx, desync)
|
||||
return VERDICT_MODIFY
|
||||
end
|
||||
else
|
||||
instance_cutoff(ctx) -- mission complete
|
||||
instance_cutoff_shim(ctx, desync) -- mission complete
|
||||
end
|
||||
else
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -270,7 +270,7 @@ 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(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
local verdict = VERDICT_PASS
|
||||
@@ -281,16 +281,49 @@ function wssize(ctx, desync)
|
||||
end
|
||||
if #desync.dis.payload>0 and (not desync.arg.forced_cutoff or in_list(desync.arg.forced_cutoff, desync.l7payload)) then
|
||||
DLOG("wssize: forced cutoff")
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
end
|
||||
return verdict
|
||||
end
|
||||
|
||||
-- nfqws1 : not available
|
||||
-- standard args : direction
|
||||
-- arg: blob - blob name to store cloned tls client hello (stored in desync, not global)
|
||||
-- arg: fallback - copy this blob if could not clone
|
||||
-- arg: sni_snt - server name type value in existing names
|
||||
-- arg: sni_snt_new - server name type value for new names
|
||||
-- arg: sni_del_ext - delete sni extension
|
||||
-- arg: sni_del - delete all names
|
||||
-- arg: sni_first - add name to the beginning
|
||||
-- arg: sni_last - add name to the end
|
||||
function tls_client_hello_clone(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
if direction_check(desync) then
|
||||
if not desync.arg.blob then
|
||||
error("fake: 'blob' arg required")
|
||||
end
|
||||
if desync.l7payload=="tls_client_hello" then
|
||||
desync[desync.arg.blob] = tls_client_hello_mod(desync.reasm_data or desync.dis.payload, desync.arg)
|
||||
if desync[desync.arg.blob] then
|
||||
DLOG("tls_client_hello_clone: cloned to desync."..desync.arg.blob)
|
||||
end
|
||||
end
|
||||
if not desync[desync.arg.blob] and desync.arg.fallback then
|
||||
DLOG("tls_client_hello_clone: desync."..desync.arg.blob.."="..desync.arg.fallback)
|
||||
desync[desync.arg.blob] = blob(desync, desync.arg.fallback)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- nfqws1 : "--dpi-desync=syndata"
|
||||
-- standard args : fooling, rawsend, reconstruct, ipfrag
|
||||
-- arg : blob=<blob> - fake payload. must fit to single packet. no segmentation possible. default - 16 zero bytes.
|
||||
-- arg : tls_mod=<list> - comma separated list of tls mods : rnd,rndsni,sni=<str>,dupsid,padencap
|
||||
-- arg : tls_mod=<list> - comma separated list of tls mods : rnd,rndsni,sni=<str>. sni=%var is supported
|
||||
function syndata(ctx, desync)
|
||||
if desync.dis.tcp then
|
||||
if bitand(desync.dis.tcp.th_flags, TH_SYN + TH_ACK)==TH_SYN then
|
||||
@@ -298,17 +331,17 @@ function syndata(ctx, desync)
|
||||
dis.payload = blob(desync, desync.arg.blob, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
|
||||
apply_fooling(desync, dis)
|
||||
if desync.arg.tls_mod then
|
||||
dis.payload = tls_mod(dis.payload, desync.arg.tls_mod, nil)
|
||||
dis.payload = tls_mod_shim(desync, dis.payload, desync.arg.tls_mod, nil)
|
||||
end
|
||||
if b_debug then DLOG("syndata: "..hexdump_dlog(dis.payload)) end
|
||||
if rawsend_dissect_ipfrag(dis, desync_opts(desync)) then
|
||||
return VERDICT_DROP
|
||||
end
|
||||
else
|
||||
instance_cutoff(ctx) -- mission complete
|
||||
instance_cutoff_shim(ctx, desync) -- mission complete
|
||||
end
|
||||
else
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -317,7 +350,7 @@ end
|
||||
-- arg : rstack - send RST,ACK instead of RST
|
||||
function rst(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -340,7 +373,8 @@ end
|
||||
-- nfqws1 : "--dpi-desync=fake"
|
||||
-- standard args : direction, payload, fooling, ip_id, rawsend, reconstruct, ipfrag
|
||||
-- arg : blob=<blob> - fake payload
|
||||
-- arg : tls_mod=<list> - comma separated list of tls mods : rnd,rndsni,sni=<str>,dupsid,padencap
|
||||
-- arg : optional - skip if blob is absent
|
||||
-- arg : tls_mod=<list> - comma separated list of tls mods : rnd,rndsni,sni=<str>,dupsid,padencap . sni=%var is supported
|
||||
function fake(ctx, desync)
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
-- by default process only outgoing known payloads
|
||||
@@ -349,9 +383,13 @@ function fake(ctx, desync)
|
||||
if not desync.arg.blob then
|
||||
error("fake: 'blob' arg required")
|
||||
end
|
||||
if desync.arg.optional and not blob_exist(desync, desync.arg.blob) then
|
||||
DLOG("fake: blob '"..desync.arg.blob.."' not found. skipped")
|
||||
return
|
||||
end
|
||||
local fake_payload = blob(desync, desync.arg.blob)
|
||||
if desync.reasm_data and desync.arg.tls_mod then
|
||||
fake_payload = tls_mod(fake_payload, desync.arg.tls_mod, desync.reasm_data)
|
||||
fake_payload = tls_mod_shim(desync, fake_payload, desync.arg.tls_mod, desync.reasm_data)
|
||||
end
|
||||
-- check debug to save CPU
|
||||
if b_debug then DLOG("fake: "..hexdump_dlog(fake_payload)) end
|
||||
@@ -368,14 +406,18 @@ 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(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
-- by default process only outgoing known payloads
|
||||
if desync.arg.optional and desync.arg.blob and not blob_exist(desync, desync.arg.blob) then
|
||||
DLOG("multisplit: blob '"..desync.arg.blob.."' not found. skipped")
|
||||
return
|
||||
end
|
||||
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
|
||||
if #data>0 and direction_check(desync) and payload_check(desync) then
|
||||
if replay_first(desync) then
|
||||
@@ -393,7 +435,14 @@ function multisplit(ctx, desync)
|
||||
local seqovl=0
|
||||
if i==0 and desync.arg.seqovl and tonumber(desync.arg.seqovl)>0 then
|
||||
seqovl = tonumber(desync.arg.seqovl)
|
||||
local pat = desync.arg.seqovl_pattern and blob(desync,desync.arg.seqovl_pattern) or "\x00"
|
||||
local pat="\x00"
|
||||
if desync.arg.seqovl_pattern then
|
||||
if desync.arg.optional and not blob_exist(desync, desync.arg.seqovl_pattern) then
|
||||
DLOG("multisplit: blob '"..desync.arg.seqovl_pattern.."' not found. using zero pattern")
|
||||
else
|
||||
pat = blob(desync,desync.arg.seqovl_pattern)
|
||||
end
|
||||
end
|
||||
part = pattern(pat,1,seqovl)..part
|
||||
end
|
||||
if b_debug then DLOG("multisplit: sending part "..(i+1).." "..(pos_start-1).."-"..(pos_end-1).." len="..#part.." seqovl="..seqovl.." : "..hexdump_dlog(part)) end
|
||||
@@ -416,20 +465,73 @@ function multisplit(ctx, desync)
|
||||
end
|
||||
end
|
||||
|
||||
-- internal function for code deduplication. do not call directly
|
||||
function pos_normalize(pos, low, hi)
|
||||
return (pos>=low and pos<hi) and (pos-low+1) or nil
|
||||
end
|
||||
-- internal function for code deduplication. do not call directly
|
||||
function pos_array_normalize(pos, low, hi)
|
||||
-- remove positions outside of hi,low range. normalize others to low
|
||||
local i=1
|
||||
while i<=#pos do
|
||||
pos[i] = pos_normalize(pos[i], low, hi)
|
||||
if pos[i] then
|
||||
i = i + 1
|
||||
else
|
||||
table.remove(pos, i);
|
||||
end
|
||||
end
|
||||
end
|
||||
-- internal function for code deduplication. do not call directly
|
||||
function multidisorder_send(desync, data, seqovl, pos)
|
||||
for i=#pos,0,-1 do
|
||||
local pos_start = pos[i] or 1
|
||||
local pos_end = i<#pos and pos[i+1]-1 or #data
|
||||
local part = string.sub(data,pos_start,pos_end)
|
||||
local ovl=0
|
||||
if i==1 and seqovl and seqovl>0 then
|
||||
if seqovl>=pos[1] then
|
||||
DLOG("multidisorder: seqovl cancelled because seqovl "..(seqovl-1).." is not less than the first split pos "..(pos[1]-1))
|
||||
else
|
||||
ovl = seqovl - 1
|
||||
local pat="\x00"
|
||||
if desync.arg.seqovl_pattern then
|
||||
if desync.arg.optional and not blob_exist(desync, desync.arg.seqovl_pattern) then
|
||||
DLOG("multidisorder: blob '"..desync.arg.seqovl_pattern.."' not found. using zero pattern")
|
||||
else
|
||||
pat = blob(desync,desync.arg.seqovl_pattern)
|
||||
end
|
||||
end
|
||||
part = pattern(pat,1,ovl)..part
|
||||
end
|
||||
end
|
||||
if b_debug then DLOG("multidisorder: sending part "..(i+1).." "..(pos_start-1).."-"..(pos_end-1).." len="..#part.." seqovl="..ovl.." : "..hexdump_dlog(part)) end
|
||||
if not rawsend_payload_segmented(desync,part,pos_start-1-ovl) then
|
||||
return VERDICT_PASS
|
||||
end
|
||||
end
|
||||
return VERDICT_DROP
|
||||
end
|
||||
|
||||
-- nfqws1 : "--dpi-desync=multidisorder"
|
||||
-- algorithm is not 100% the same as in nfqws1. multi-segment queries can produce different segment ordering.
|
||||
-- standard args : direction, payload, fooling, ip_id, rawsend, reconstruct, ipfrag
|
||||
-- arg : pos=<postmarker list> . position marker list. example : "1,host,midsld+1,-10"
|
||||
-- arg : seqovl=N . decrease seq number of the second segment in the original order by N and fill N bytes with pattern (default - all zero). N must be less than the first split pos.
|
||||
-- arg : seqovl_pattern=<blob> . override pattern
|
||||
-- arg : blob=<blob> - use this data instead of desync.dis.payload
|
||||
-- arg : blob=<blob> - use this data instead of reasm_data
|
||||
-- arg : optional - skip if blob is absent. use zero pattern if seqovl_pattern blob is absent
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function multidisorder(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
-- by default process only outgoing known payloads
|
||||
if desync.arg.optional and desync.arg.blob and not blob_exist(desync, desync.arg.blob) then
|
||||
DLOG("multidisorder: blob '"..desync.arg.blob.."' not found. skipped")
|
||||
return
|
||||
end
|
||||
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
|
||||
if #data>0 and direction_check(desync) and payload_check(desync) then
|
||||
if replay_first(desync) then
|
||||
@@ -440,32 +542,16 @@ function multidisorder(ctx, desync)
|
||||
if b_debug then DLOG("multidisorder: resolved split pos: "..table.concat(zero_based_pos(pos)," ")) end
|
||||
delete_pos_1(pos) -- cannot split at the first byte
|
||||
if #pos>0 then
|
||||
for i=#pos,0,-1 do
|
||||
local pos_start = pos[i] or 1
|
||||
local pos_end = i<#pos and pos[i+1]-1 or #data
|
||||
local part = string.sub(data,pos_start,pos_end)
|
||||
local seqovl=0
|
||||
if i==1 and desync.arg.seqovl then
|
||||
seqovl = resolve_pos(data, desync.l7payload, desync.arg.seqovl)
|
||||
if not seqovl then
|
||||
DLOG("multidisorder: seqovl cancelled because could not resolve marker '"..desync.arg.seqovl.."'")
|
||||
seqovl = 0
|
||||
else
|
||||
seqovl = seqovl - 1
|
||||
if seqovl>=(pos[1]-1) then
|
||||
DLOG("multidisorder: seqovl cancelled because seqovl "..seqovl.." is not less than the first split pos "..(pos[1]-1))
|
||||
seqovl = 0
|
||||
else
|
||||
local pat = desync.arg.seqovl_pattern and blob(desync,desync.arg.seqovl_pattern) or "\x00"
|
||||
part = pattern(pat,1,seqovl)..part
|
||||
end
|
||||
end
|
||||
end
|
||||
if b_debug then DLOG("multidisorder: sending part "..(i+1).." "..(pos_start-1).."-"..(pos_end-1).." len="..#part.." seqovl="..seqovl.." : "..hexdump_dlog(part)) end
|
||||
if not rawsend_payload_segmented(desync,part,pos_start-1-seqovl) then
|
||||
return VERDICT_PASS
|
||||
local seqovl
|
||||
if desync.arg.seqovl then
|
||||
seqovl = resolve_pos(data, desync.l7payload, desync.arg.seqovl)
|
||||
if not seqovl then
|
||||
DLOG("multidisorder: seqovl cancelled because could not resolve marker '"..desync.arg.seqovl.."'")
|
||||
end
|
||||
end
|
||||
if multidisorder_send(desync, data, seqovl, pos)==VERDICT_PASS then
|
||||
return VERDICT_PASS
|
||||
end
|
||||
replay_drop_set(desync)
|
||||
return desync.arg.nodrop and VERDICT_PASS or VERDICT_DROP
|
||||
else
|
||||
@@ -481,6 +567,60 @@ function multidisorder(ctx, desync)
|
||||
end
|
||||
end
|
||||
|
||||
-- nfqws1 : "--dpi-desync=multidisorder". segment ordering is the same as in nfqws1
|
||||
-- standard args : direction, payload, fooling, ip_id, rawsend, reconstruct, ipfrag
|
||||
-- arg : pos=<postmarker list> . position marker list. example : "1,host,midsld+1,-10"
|
||||
-- arg : seqovl=N . decrease seq number of the second segment in the original order by N and fill N bytes with pattern (default - all zero). N must be less than the first split pos.
|
||||
-- arg : seqovl_pattern=<blob> . override pattern
|
||||
-- arg : optional - use zero pattern if seqovl_pattern blob is absent
|
||||
function multidisorder_legacy(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
-- by default process only outgoing known payloads
|
||||
local data = desync.dis.payload
|
||||
local fulldata = desync.reasm_data
|
||||
if #data>0 and direction_check(desync) and payload_check(desync) then
|
||||
local range_low = (desync.reasm_offset or 0) + 1
|
||||
local range_hi = range_low + #data
|
||||
local spos = desync.arg.pos or "2"
|
||||
-- check debug to save CPU
|
||||
if b_debug then DLOG("multidisorder_legacy: split pos: "..spos) end
|
||||
local pos = resolve_multi_pos(fulldata, desync.l7payload, spos)
|
||||
if b_debug then DLOG("multidisorder_legacy: resolved split pos: "..table.concat(zero_based_pos(pos)," ")) end
|
||||
DLOG("multidisorder_legacy: reasm piece range: "..(range_low-1).."-"..(range_hi-2))
|
||||
pos_array_normalize(pos, range_low, range_hi)
|
||||
delete_pos_1(pos) -- cannot split at the first byte
|
||||
if #pos>0 then
|
||||
if b_debug then DLOG("multidisorder_legacy: normalized split pos: "..table.concat(zero_based_pos(pos)," ")) end
|
||||
local seqovl
|
||||
if desync.arg.seqovl then
|
||||
seqovl = resolve_pos(fulldata, desync.l7payload, desync.arg.seqovl)
|
||||
if seqovl then
|
||||
DLOG("multidisorder_legacy: resolved seqovl pos: "..(seqovl-1))
|
||||
seqovl = pos_normalize(seqovl, range_low, range_hi)
|
||||
if seqovl then
|
||||
DLOG("multidisorder_legacy: normalized seqovl pos: "..(seqovl-1))
|
||||
else
|
||||
DLOG("multidisorder_legacy: normalized seqovl pos is outside of the reasm piece range")
|
||||
end
|
||||
else
|
||||
DLOG("multidisorder_legacy: seqovl cancelled because could not resolve marker '"..desync.arg.seqovl.."'")
|
||||
end
|
||||
end
|
||||
return multidisorder_send(desync, data, seqovl, pos)
|
||||
else
|
||||
DLOG("multidisorder_legacy: no normalized split pos in this packet")
|
||||
-- send as is with applied options
|
||||
if rawsend_payload_segmented(desync) then
|
||||
return VERDICT_DROP
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- nfqws1 : "--dpi-desync=hostfakesplit"
|
||||
-- standard args : direction, payload, fooling, ip_id, rawsend, reconstruct. FOOLING AND REPEATS APPLIED ONLY TO FAKES.
|
||||
-- arg : host=<str> - hostname template. generate hosts like "random.template". example : e8nzn.vk.com
|
||||
@@ -488,14 +628,18 @@ 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(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
-- by default process only outgoing known payloads
|
||||
if desync.arg.optional and desync.arg.blob and not blob_exist(desync, desync.arg.blob) then
|
||||
DLOG("hostfakesplit: blob '"..desync.arg.blob.."' not found. skipped")
|
||||
return
|
||||
end
|
||||
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
|
||||
if #data>0 and direction_check(desync) and payload_check(desync) then
|
||||
if replay_first(desync) then
|
||||
@@ -600,15 +744,19 @@ end
|
||||
-- arg : pattern=<blob> . fill fake parts with this pattern
|
||||
-- arg : seqovl=N . decrease seq number of the first segment by N and fill N bytes with pattern (default - all zero)
|
||||
-- arg : seqovl_pattern=<blob> . override seqovl pattern
|
||||
-- arg : blob=<blob> - use this data instead of desync.dis.payload
|
||||
-- arg : blob=<blob> - use this data instead of reasm_data
|
||||
-- arg : optional - skip if blob is absent. use zero pattern if seqovl_pattern blob is absent
|
||||
-- arg : nodrop - do not drop current dissect
|
||||
function fakedsplit(ctx, desync)
|
||||
if not desync.dis.tcp then
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
-- by default process only outgoing known payloads
|
||||
if desync.arg.optional and desync.arg.blob and not blob_exist(desync, desync.arg.blob) then
|
||||
DLOG("fakedsplit: blob '"..desync.arg.blob.."' not found. skipped")
|
||||
return
|
||||
end
|
||||
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
|
||||
if #data>0 and direction_check(desync) and payload_check(desync) then
|
||||
if replay_first(desync) then
|
||||
@@ -616,7 +764,7 @@ function fakedsplit(ctx, desync)
|
||||
local pos = resolve_pos(data, desync.l7payload, spos)
|
||||
if pos then
|
||||
if pos == 1 then
|
||||
DLOG("multidisorder: split pos resolved to 0. cannot split.")
|
||||
DLOG("fakedsplit: split pos resolved to 0. cannot split.")
|
||||
else
|
||||
if b_debug then DLOG("fakedsplit: resolved split pos: "..tostring(pos-1)) end
|
||||
|
||||
@@ -640,7 +788,14 @@ function fakedsplit(ctx, desync)
|
||||
local seqovl=0
|
||||
if desync.arg.seqovl and tonumber(desync.arg.seqovl)>0 then
|
||||
seqovl = tonumber(desync.arg.seqovl)
|
||||
pat = desync.arg.seqovl_pattern and blob(desync,desync.arg.seqovl_pattern) or "\x00"
|
||||
pat="\x00"
|
||||
if desync.arg.seqovl_pattern then
|
||||
if desync.arg.optional and not blob_exist(desync, desync.arg.seqovl_pattern) then
|
||||
DLOG("fakedsplit: blob '"..desync.arg.seqovl_pattern.."' not found. using zero pattern")
|
||||
else
|
||||
pat = blob(desync,desync.arg.seqovl_pattern)
|
||||
end
|
||||
end
|
||||
part = pattern(pat,1,seqovl)..part
|
||||
end
|
||||
if b_debug then DLOG("fakedsplit: sending real part 1 : 0-"..(pos-2).." len="..#part.." seqovl="..seqovl.." : "..hexdump_dlog(part)) end
|
||||
@@ -694,14 +849,18 @@ 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(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
-- by default process only outgoing known payloads
|
||||
if desync.arg.optional and desync.arg.blob and not blob_exist(desync, desync.arg.blob) then
|
||||
DLOG("fakeddisorder: blob '"..desync.arg.blob.."' not found. skipped")
|
||||
return
|
||||
end
|
||||
local data = blob_or_def(desync, desync.arg.blob) or desync.reasm_data or desync.dis.payload
|
||||
if #data>0 and direction_check(desync) and payload_check(desync) then
|
||||
if replay_first(desync) then
|
||||
@@ -709,7 +868,7 @@ function fakeddisorder(ctx, desync)
|
||||
local pos = resolve_pos(data, desync.l7payload, spos)
|
||||
if pos then
|
||||
if pos == 1 then
|
||||
DLOG("multidisorder: split pos resolved to 0. cannot split.")
|
||||
DLOG("fakeddisorder: split pos resolved to 0. cannot split.")
|
||||
else
|
||||
if b_debug then DLOG("fakeddisorder: resolved split pos: "..tostring(pos-1)) end
|
||||
|
||||
@@ -738,7 +897,14 @@ function fakeddisorder(ctx, desync)
|
||||
DLOG("fakeddisorder: seqovl cancelled because seqovl "..seqovl.." is not less than the split pos "..(pos-1))
|
||||
seqovl = 0
|
||||
else
|
||||
local pat = desync.arg.seqovl_pattern and blob(desync,desync.arg.seqovl_pattern) or "\x00"
|
||||
local pat="\x00"
|
||||
if desync.arg.seqovl_pattern then
|
||||
if desync.arg.optional and not blob_exist(desync, desync.arg.seqovl_pattern) then
|
||||
DLOG("fakeddisorder: blob '"..desync.arg.seqovl_pattern.."' not found. using zero pattern")
|
||||
else
|
||||
pat = blob(desync,desync.arg.seqovl_pattern)
|
||||
end
|
||||
end
|
||||
part = pattern(pat,1,seqovl)..part
|
||||
end
|
||||
else
|
||||
@@ -795,16 +961,20 @@ 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(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
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 +988,14 @@ function tcpseg(ctx, desync)
|
||||
local seqovl=0
|
||||
if desync.arg.seqovl and tonumber(desync.arg.seqovl)>0 then
|
||||
seqovl = tonumber(desync.arg.seqovl)
|
||||
local pat = desync.arg.seqovl_pattern and blob(desync,desync.arg.seqovl_pattern) or "\x00"
|
||||
local pat="\x00"
|
||||
if desync.arg.seqovl_pattern then
|
||||
if desync.arg.optional and not blob_exist(desync, desync.arg.seqovl_pattern) then
|
||||
DLOG("tcpseg: blob '"..desync.arg.seqovl_pattern.."' not found. using zero pattern")
|
||||
else
|
||||
pat = blob(desync,desync.arg.seqovl_pattern)
|
||||
end
|
||||
end
|
||||
part = pattern(pat,1,seqovl)..part
|
||||
end
|
||||
if b_debug then DLOG("tcpseg: sending "..(pos[1]-1).."-"..(pos[2]-1).." len="..#part.." seqovl="..seqovl.." : "..hexdump_dlog(part)) end
|
||||
@@ -841,7 +1018,7 @@ end
|
||||
-- arg : pattern_offset=N . offset in the pattern. 0 by default
|
||||
function udplen(ctx, desync)
|
||||
if not desync.dis.udp then
|
||||
instance_cutoff(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
return
|
||||
end
|
||||
direction_cutoff_opposite(ctx, desync)
|
||||
@@ -874,15 +1051,15 @@ 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(ctx)
|
||||
instance_cutoff_shim(ctx, desync)
|
||||
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)
|
||||
|
||||
502
lua/zapret-auto.lua
Normal file
502
lua/zapret-auto.lua
Normal file
@@ -0,0 +1,502 @@
|
||||
-- standard automation/orchestration code
|
||||
-- this is related to making dynamic strategy decisions without rewriting or altering strategy function code
|
||||
-- orchestrators can decide which instances to call or not to call or pass them dynamic arguments
|
||||
-- failure and success detectors test potential block conditions for orchestrators
|
||||
|
||||
-- standard host key generator for per-host storage
|
||||
-- arg: reqhost - require hostname, do not work with ip
|
||||
-- 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
|
||||
autostate = {}
|
||||
end
|
||||
if not autostate[askey] then
|
||||
autostate[askey] = {}
|
||||
end
|
||||
if not autostate[askey][hostkey] then
|
||||
autostate[askey][hostkey] = {}
|
||||
end
|
||||
return autostate[askey][hostkey]
|
||||
end
|
||||
-- per-connection storage
|
||||
function automate_conn_record(desync)
|
||||
if not desync.track.lua_state.automate then
|
||||
desync.track.lua_state.automate = {}
|
||||
end
|
||||
return desync.track.lua_state.automate
|
||||
end
|
||||
|
||||
-- counts failure, optionally (if crec is given) prevents dup failure counts in a single connection
|
||||
-- if 'maxtime' between failures is exceeded then failure count is reset
|
||||
-- return true if threshold ('fails') is reached
|
||||
-- hres is host record. host or ip bound table
|
||||
-- cres is connection record. connection bound table
|
||||
function automate_failure_counter(hrec, crec, fails, maxtime)
|
||||
if crec and crec.failure then
|
||||
DLOG("automate: duplicate failure in the same connection. not counted")
|
||||
else
|
||||
if crec then crec.failure = true end
|
||||
local tnow=os.time()
|
||||
if not hrec.failure_time_last then
|
||||
hrec.failure_time_last = tnow
|
||||
end
|
||||
if not hrec.failure_counter then
|
||||
hrec.failure_counter = 0
|
||||
elseif tnow>(hrec.failure_time_last + maxtime) then
|
||||
DLOG("automate: failure counter reset because last failure was "..(tnow - hrec.failure_time_last).." seconds ago")
|
||||
hrec.failure_counter = 0
|
||||
end
|
||||
hrec.failure_counter = hrec.failure_counter + 1
|
||||
hrec.failure_time_last = tnow
|
||||
if b_debug then DLOG("automate: failure counter "..hrec.failure_counter..(fails and ('/'..fails) or '')) end
|
||||
if fails and hrec.failure_counter>=fails then
|
||||
hrec.failure_counter = nil -- reset counter
|
||||
return true
|
||||
end
|
||||
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
|
||||
local sld1 = dissect_nld(hostname,2)
|
||||
local sld2 = dissect_nld(ds.domain,2)
|
||||
return sld2 and sld1~=sld2
|
||||
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:
|
||||
-- incoming RST
|
||||
-- incoming http redirection
|
||||
-- outgoing retransmissions
|
||||
-- udp too much out with too few in
|
||||
-- arg: maxseq=<rseq> - tcp: test retransmissions only within this relative sequence. default is 32K
|
||||
-- arg: retrans=N - tcp: retrans count threshold. default is 3
|
||||
-- arg: reset - send RST to retransmitter to break long wait
|
||||
-- arg: inseq=<rseq> - tcp: maximum relative sequence number to treat incoming RST as DPI reset. default is 4K
|
||||
-- arg: no_http_redirect - tcp: disable http_reply dpi redirect trigger
|
||||
-- arg: no_rst - tcp: disable incoming RST trigger
|
||||
-- arg: udp_out - udp: >= outgoing udp packets. default is 4
|
||||
-- arg: udp_in - udp: with <= incoming udp packets. default is 1
|
||||
function standard_failure_detector(desync, crec)
|
||||
local arg = standard_detector_defaults(desync.arg)
|
||||
local trigger = false
|
||||
if desync.dis.tcp then
|
||||
local seq = pos_get(desync,'s')
|
||||
if desync.outgoing then
|
||||
if #desync.dis.payload>0 and arg.retrans and arg.maxseq>0 and seq<=arg.maxseq and (crec.retrans or 0)<arg.retrans then
|
||||
if is_retransmission(desync) then
|
||||
crec.retrans = crec.retrans and (crec.retrans+1) or 1
|
||||
DLOG("standard_failure_detector: retransmission "..crec.retrans.."/"..arg.retrans)
|
||||
trigger = crec.retrans>=arg.retrans
|
||||
if trigger and arg.reset then
|
||||
local dis = deepcopy(desync.dis)
|
||||
dis.payload = nil
|
||||
dis_reverse(dis)
|
||||
dis.tcp.th_flags = TH_RST
|
||||
dis.tcp.th_win = desync.track and desync.track.pos.reverse.tcp.winsize or 64
|
||||
dis.tcp.options = nil
|
||||
if dis.ip6 then
|
||||
dis.ip6.ip6_flow = (desync.track and desync.track.pos.reverse.ip6_flow) and desync.track.pos.reverse.ip6_flow or 0x60000000;
|
||||
end
|
||||
DLOG("standard_failure_detector: sending RST to retransmitter")
|
||||
rawsend_dissect(dis, {ifout = desync.ifin})
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if not arg.no_rst and arg.inseq>0 and bitand(desync.dis.tcp.th_flags, TH_RST)~=0 and seq>=1 then
|
||||
trigger = seq<=arg.inseq
|
||||
if b_debug then
|
||||
if trigger then
|
||||
DLOG("standard_failure_detector: incoming RST s"..seq.." in range s"..arg.inseq)
|
||||
else
|
||||
DLOG("standard_failure_detector: not counting incoming RST s"..seq.." beyond s"..arg.inseq)
|
||||
end
|
||||
end
|
||||
elseif not arg.no_http_redirect and desync.l7payload=="http_reply" and desync.track.hostname then
|
||||
local hdis = http_dissect_reply(desync.dis.payload)
|
||||
if hdis and (hdis.code==302 or hdis.code==307) and hdis.headers.location and hdis.headers.location then
|
||||
trigger = is_dpi_redirect(desync.track.hostname, hdis.headers.location.value)
|
||||
if b_debug then
|
||||
if trigger then
|
||||
DLOG("standard_failure_detector: http redirect "..hdis.code.." to '"..hdis.headers.location.value.."'. looks like DPI redirect.")
|
||||
else
|
||||
DLOG("standard_failure_detector: http redirect "..hdis.code.." to '"..hdis.headers.location.value.."'. NOT a DPI redirect.")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif desync.dis.udp then
|
||||
if desync.outgoing then
|
||||
if arg.udp_out>0 then
|
||||
local pos_out = pos_get(desync,'n',false)
|
||||
local pos_in = pos_get(desync,'n',true)
|
||||
trigger = pos_out>=arg.udp_out and pos_in<=arg.udp_in
|
||||
if trigger then
|
||||
if b_debug then
|
||||
DLOG("standard_failure_detector: arg.udp_out "..pos_out..">="..arg.udp_out.." arg.udp_in "..pos_in.."<="..arg.udp_in)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return trigger
|
||||
end
|
||||
|
||||
-- standard success detector
|
||||
-- success means previous failures were temporary and counter should be reset
|
||||
-- detected successes:
|
||||
-- tcp: outgoing seq is beyond 'maxseq' and maxseq>0
|
||||
-- tcp: incoming seq is beyond 'inseq' and inseq>0
|
||||
-- udp: incoming packets count > `udp_in` and `udp_out`>0
|
||||
-- arg: maxseq=<rseq> - tcp: success if outgoing relative sequence is beyond this value. default is 32K
|
||||
-- arg: inseq=<rseq> - tcp: success if incoming relative sequence is beyond this value. default is 4K
|
||||
-- arg: udp_out - udp : must be nil or >0 to test udp_in
|
||||
-- arg: udp_in - udp: if number if incoming packets > udp_in it means success
|
||||
function standard_success_detector(desync, crec)
|
||||
local arg = standard_detector_defaults(desync.arg)
|
||||
if desync.dis.tcp then
|
||||
local seq = pos_get(desync,'s')
|
||||
if desync.outgoing then
|
||||
if arg.maxseq>0 and seq>arg.maxseq then
|
||||
DLOG("standard_success_detector: outgoing s"..seq.." is beyond s"..arg.maxseq..". treating connection as successful")
|
||||
return true
|
||||
end
|
||||
else
|
||||
if arg.inseq>0 and seq>arg.inseq then
|
||||
DLOG("standard_success_detector: incoming s"..seq.." is beyond s"..arg.inseq..". treating connection as successful")
|
||||
return true
|
||||
end
|
||||
end
|
||||
elseif desync.dis.udp then
|
||||
if not desync.outgoing then
|
||||
local pos = pos_get(desync,'n')
|
||||
if arg.udp_out>0 and pos>arg.udp_in then
|
||||
if b_debug then
|
||||
DLOG("standard_success_detector: arg.udp_in "..pos..">"..arg.udp_in)
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- calls success and failure detectors
|
||||
-- resets counter if success is detected
|
||||
-- increases counter if failure is detected
|
||||
-- returns true if failure counter exceeds threshold
|
||||
function automate_failure_check(desync, hrec, crec)
|
||||
if crec.nocheck then return false end
|
||||
|
||||
local failure_detector, success_detector
|
||||
if desync.arg.failure_detector then
|
||||
if type(_G[desync.arg.failure_detector])~="function" then
|
||||
error("automate: invalid failure detector function '"..desync.arg.failure_detector.."'")
|
||||
end
|
||||
failure_detector = _G[desync.arg.failure_detector]
|
||||
else
|
||||
failure_detector = standard_failure_detector
|
||||
end
|
||||
if desync.arg.success_detector then
|
||||
if type(_G[desync.arg.success_detector])~="function" then
|
||||
error("automate: invalid success detector function '"..desync.arg.success_detector.."'")
|
||||
end
|
||||
success_detector = _G[desync.arg.success_detector]
|
||||
else
|
||||
success_detector = standard_success_detector
|
||||
end
|
||||
|
||||
if success_detector(desync, crec) then
|
||||
crec.nocheck = true
|
||||
DLOG("automate: success detected")
|
||||
automate_failure_counter_reset(hrec)
|
||||
return false
|
||||
end
|
||||
if failure_detector(desync, crec) then
|
||||
crec.nocheck = true
|
||||
DLOG("automate: failure detected")
|
||||
local fails = tonumber(desync.arg.fails) or 3
|
||||
local maxtime = tonumber(desync.arg.time) or 60
|
||||
return automate_failure_counter(hrec, crec, fails, maxtime)
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
-- circularily change strategy numbers when failure count reaches threshold ('fails')
|
||||
-- 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: success_detector - success detector function name
|
||||
-- arg: failure_detector - failure detector function name
|
||||
-- arg: hostkey - hostkey generator function name
|
||||
-- args for failure detector - see standard_failure_detector or your own detector
|
||||
-- args for success detector - see standard_success_detector or your own detector
|
||||
-- args for hostkey generator - see standard_hostkey or your own generator
|
||||
-- test case: --in-range=-s34228 --lua-desync=circular --lua-desync=argdebug:strategy=1 --lua-desync=argdebug:strategy=2
|
||||
function circular(ctx, desync)
|
||||
local function count_strategies(hrec)
|
||||
if not hrec.ctstrategy then
|
||||
local uniq={}
|
||||
local n=0
|
||||
for i,instance in pairs(desync.plan) do
|
||||
if instance.arg.strategy then
|
||||
n = tonumber(instance.arg.strategy)
|
||||
if not n or n<1 then
|
||||
error("circular: strategy number '"..tostring(instance.arg.strategy).."' is invalid")
|
||||
end
|
||||
uniq[tonumber(instance.arg.strategy)] = true
|
||||
if instance.arg.final then
|
||||
hrec.final = n
|
||||
end
|
||||
end
|
||||
end
|
||||
n=0
|
||||
for i,v in pairs(uniq) do
|
||||
n=n+1
|
||||
end
|
||||
if n~=#uniq then
|
||||
error("circular: strategies numbers must start from 1 and increment. gaps are not allowed.")
|
||||
end
|
||||
hrec.ctstrategy = n
|
||||
end
|
||||
end
|
||||
|
||||
-- take over execution. prevent further instance execution in case of error
|
||||
orchestrate(ctx, desync)
|
||||
|
||||
if not desync.track then
|
||||
DLOG_ERR("circular: conntrack is missing but required")
|
||||
return
|
||||
end
|
||||
|
||||
local hrec = automate_host_record(desync)
|
||||
if not hrec then
|
||||
DLOG("circular: passing with no tampering")
|
||||
return
|
||||
end
|
||||
|
||||
count_strategies(hrec)
|
||||
if hrec.ctstrategy==0 then
|
||||
error("circular: add strategy=N tag argument to each following instance ! N must start from 1 and increment")
|
||||
end
|
||||
if not hrec.nstrategy then
|
||||
DLOG("circular: start from strategy 1")
|
||||
hrec.nstrategy = 1
|
||||
end
|
||||
|
||||
local verdict = VERDICT_PASS
|
||||
if hrec.final~=hrec.nstrategy then
|
||||
local crec = automate_conn_record(desync)
|
||||
if automate_failure_check(desync, hrec, crec) then
|
||||
hrec.nstrategy = (hrec.nstrategy % hrec.ctstrategy) + 1
|
||||
DLOG("circular: rotate strategy to "..hrec.nstrategy)
|
||||
if hrec.nstrategy == hrec.final then
|
||||
DLOG("circular: final strategy "..hrec.final.." reached. will rotate no more.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
DLOG("circular: current strategy "..hrec.nstrategy)
|
||||
while true do
|
||||
local instance = plan_instance_pop(desync)
|
||||
if not instance then break end
|
||||
if instance.arg.strategy and tonumber(instance.arg.strategy)==hrec.nstrategy then
|
||||
verdict = plan_instance_execute(desync, verdict, instance)
|
||||
end
|
||||
end
|
||||
|
||||
return verdict
|
||||
end
|
||||
|
||||
-- test iff functions
|
||||
function cond_true(desync)
|
||||
return true
|
||||
end
|
||||
function cond_false(desync)
|
||||
return false
|
||||
end
|
||||
-- arg: percent - of true . 50 by default
|
||||
function cond_random(desync)
|
||||
return math.random(0,99)<(tonumber(desync.arg.percent) or 50)
|
||||
end
|
||||
-- this iif function detects packets having 'arg.pattern' string in their payload
|
||||
-- test case : --lua-desync=condition:iff=cond_payload_str:pattern=1234 --lua-desync=argdebug:testarg=1 --lua-desync=argdebug:testarg=2:morearg=xyz
|
||||
-- test case (true) : echo aaz1234zzz | ncat -4u 1.1.1.1 443
|
||||
-- test case (false) : echo aaze124zzz | ncat -4u 1.1.1.1 443
|
||||
function cond_payload_str(desync)
|
||||
if not desync.arg.pattern then
|
||||
error("cond_payload_str: missing 'pattern'")
|
||||
end
|
||||
return string.find(desync.dis.payload,desync.arg.pattern,1,true)
|
||||
end
|
||||
-- check iff function available. error if not
|
||||
function require_iff(desync, name)
|
||||
if not desync.arg.iff then
|
||||
error(name..": missing 'iff' function")
|
||||
end
|
||||
if type(_G[desync.arg.iff])~="function" then
|
||||
error(name..": invalid 'iff' function '"..desync.arg.iff.."'")
|
||||
end
|
||||
end
|
||||
-- execute further desync instances only if user-provided 'iff' function returns true
|
||||
-- for example, this can be used by custom protocol detectors
|
||||
-- arg: iff - condition function. takes desync as arg and returns bool. (cant use 'if' because of reserved word)
|
||||
-- arg: neg - invert condition function result
|
||||
-- test case : --lua-desync=condition:iff=cond_random --lua-desync=argdebug:testarg=1 --lua-desync=argdebug:testarg=2:morearg=xyz
|
||||
function condition(ctx, desync)
|
||||
require_iff(desync, "condition")
|
||||
orchestrate(ctx, desync)
|
||||
if logical_xor(_G[desync.arg.iff](desync), desync.arg.neg) then
|
||||
DLOG("condition: true")
|
||||
return replay_execution_plan(desync)
|
||||
else
|
||||
DLOG("condition: false")
|
||||
plan_clear(desync)
|
||||
end
|
||||
end
|
||||
-- clear execution plan if user provided 'iff' functions returns true
|
||||
-- can be used with other orchestrators to stop execution conditionally
|
||||
-- arg: iff - condition function. takes desync as arg and returns bool. (cant use 'if' because of reserved word)
|
||||
-- arg: neg - invert condition function result
|
||||
-- test case : --in-range=-s1 --lua-desync=circular --lua-desync=stopif:iff=cond_random:strategy=1 --lua-desync=argdebug:strategy=1 --lua-desync=argdebug:strategy=2
|
||||
function stopif(ctx, desync)
|
||||
require_iff(desync, "stopif")
|
||||
orchestrate(ctx, desync)
|
||||
if logical_xor(_G[desync.arg.iff](desync), desync.arg.neg) then
|
||||
DLOG("stopif: true")
|
||||
plan_clear(desync)
|
||||
else
|
||||
-- do not do anything. allow other orchestrator to finish the plan
|
||||
DLOG("stopif: false")
|
||||
end
|
||||
end
|
||||
|
||||
-- repeat following 'instances' 'repeats' times, execute others with no tampering
|
||||
-- arg: instances - number of following instances to be repeated. 1 by default
|
||||
-- arg: repeats - number of repeats
|
||||
-- arg: iff - condition function to continue execution. takes desync as arg and returns bool. (cant use 'if' because of reserved word)
|
||||
-- arg: neg - invert condition function result
|
||||
-- arg: stop - do not replay remaining execution plan after 'instances'
|
||||
-- arg: clear - clear execution plan after 'instances'
|
||||
-- test case : --lua-desync=repeater:repeats=2:instances=2 --lua-desync=argdebug:v=1 --lua-desync=argdebug:v=2 --lua-desync=argdebug:v=3
|
||||
function repeater(ctx, desync)
|
||||
local repeats = tonumber(desync.arg.repeats)
|
||||
if not repeats then
|
||||
error("repeat: missing 'repeats'")
|
||||
end
|
||||
local iff = desync.arg.iff or "cond_true"
|
||||
if type(_G[iff])~="function" then
|
||||
error(name..": invalid 'iff' function '"..iff.."'")
|
||||
end
|
||||
orchestrate(ctx, desync)
|
||||
local neg = desync.arg.neg
|
||||
local stop = desync.arg.stop
|
||||
local clear = desync.arg.clear
|
||||
local verdict = VERDICT_PASS
|
||||
local instances = tonumber(desync.arg.instances) or 1
|
||||
local repinst = desync.func_instance
|
||||
if instances>#desync.plan then
|
||||
instances = #desync.plan
|
||||
end
|
||||
-- save plan copy
|
||||
local plancopy = deepcopy(desync.plan)
|
||||
for r=1,repeats do
|
||||
if not logical_xor(_G[iff](desync), neg) then
|
||||
DLOG("repeater: break by iff")
|
||||
break
|
||||
end
|
||||
DLOG("repeater: "..repinst.." "..r.."/"..repeats)
|
||||
-- nested orchestrators can also pop
|
||||
local ct_end = #desync.plan - instances
|
||||
repeat
|
||||
local instance = plan_instance_pop(desync)
|
||||
verdict = plan_instance_execute(desync, verdict, instance)
|
||||
until #desync.plan <= ct_end
|
||||
-- rollback desync plan
|
||||
desync.plan = deepcopy(plancopy)
|
||||
end
|
||||
-- remove repeated instances from desync plan
|
||||
for i=1,instances do
|
||||
table.remove(desync.plan,1)
|
||||
end
|
||||
if clear then
|
||||
plan_clear(desync)
|
||||
return verdict
|
||||
elseif stop then
|
||||
return verdict
|
||||
end
|
||||
-- replay the rest
|
||||
return verdict_aggregate(verdict, replay_execution_plan(desync))
|
||||
end
|
||||
1433
lua/zapret-lib.lua
1433
lua/zapret-lib.lua
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user