mirror of
https://github.com/bol-van/zapret2.git
synced 2026-03-17 07:09:44 +00:00
Compare commits
410 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
5
.github/workflows/build.yml
vendored
5
.github/workflows/build.yml
vendored
@@ -26,6 +26,8 @@ jobs:
|
||||
tool: aarch64-unknown-linux-musl
|
||||
- arch: arm
|
||||
tool: arm-unknown-linux-musleabi
|
||||
- arch: arm-old
|
||||
tool: arm-unknown-linux-musleabi
|
||||
# - arch: armhf
|
||||
# tool: arm-unknown-linux-musleabihf
|
||||
# - arch: armv7
|
||||
@@ -108,7 +110,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 ]] || [[ "$ARCH" == arm-old ]]; then
|
||||
# use classic lua
|
||||
wget -qO- https://www.lua.org/ftp/lua-${LUA_RELEASE}.tar.gz | tar -xz
|
||||
(
|
||||
@@ -527,6 +529,7 @@ jobs:
|
||||
*-android-x86_64 ) run_dir android-x86_64 ;;
|
||||
*-freebsd-x86_64 ) run_dir freebsd-x86_64 ;;
|
||||
*-linux-arm ) run_dir linux-arm ;;
|
||||
*-linux-arm-old ) run_dir linux-arm-old ;;
|
||||
*-linux-arm64 ) run_dir linux-arm64 ;;
|
||||
*-linux-mips64 ) run_dir linux-mips64 ;;
|
||||
*-linux-mipselsf ) run_dir linux-mipsel ;;
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -34,3 +34,102 @@ 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
|
||||
|
||||
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 !
|
||||
|
||||
4596
docs/manual.md
Normal file
4596
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.
|
||||
@@ -40,7 +52,7 @@ zapret2 - инструмент для таких энтузиастов. Но э
|
||||
|
||||
## С чего начать
|
||||
|
||||
Хотелось бы избежать "талмуда" на главной странице. Поэтому начнем со способа запуска *nfqws2* и описания способов портирования стратегий *nfqws1* - как в *nfqws2* сделать то же самое, что можно было в *nfqws1*.
|
||||
Хотелось бы избежать [талмуда](manual.md) на главной странице. Поэтому начнем со способа запуска *nfqws2* и описания способов портирования стратегий *nfqws1* - как в *nfqws2* сделать то же самое, что можно было в *nfqws1*.
|
||||
Когда вы поймете как это работает, вы можете посмотреть LUA код, находящийся "под капотом". Разобрать как он работает, попробовать написать что-то свое.
|
||||
"талмуд" обязательно будет, как он есть у любых более-менее сложных проектов. Он нужен как справочник.
|
||||
|
||||
@@ -155,7 +167,7 @@ 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.
|
||||
|
||||
@@ -289,18 +301,15 @@ 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" и сразу же отпустит пакет.
|
||||
|
||||
Почему именно `-d10` ? Чтобы хватило для отработки большинства вариантов стратегий, учитывая возможные ретрансмиссии и плохую связь. В winws2 по умолчанию включен параметр `--wf-tcp-empty=0`. Он блокирует перехват пустых пакетов с ACK, что позволяет примерно в 2 раза сэкономить на процессоре при интенсивных скачиваниях. Пустые ACK в большинстве стратегий не нужны. Но это же и ломает счетчик "n" - он не будет показывать реальное количество пакетов по соединению. Счетчик "d" работать будет как надо.
|
||||
|
||||
Так же везде расставлены фильтры по 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.
|
||||
@@ -361,7 +370,7 @@ start "zapret: http,https,quic" /min "%~dp0winws2.exe" ^
|
||||
--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
|
||||
```
|
||||
|
||||
|
||||
BIN
files/fake/dns.bin
Normal file
BIN
files/fake/dns.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
|
||||
}
|
||||
38
init.d/custom.d.examples.linux/50-dht4all
Normal file
38
init.d/custom.d.examples.linux/50-dht4all
Normal file
@@ -0,0 +1,38 @@
|
||||
# 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}"
|
||||
|
||||
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_connbytes 1:1"
|
||||
|
||||
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_connbytes 1"
|
||||
|
||||
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
|
||||
}
|
||||
32
init.d/custom.d.examples.linux/50-wg4all
Normal file
32
init.d/custom.d.examples.linux/50-wg4all
Normal file
@@ -0,0 +1,32 @@
|
||||
# this custom script runs desync to all wireguard handshake initiation packets
|
||||
# NOTE: this works for original wireguard and may not work for 3rd party implementations such as xray
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_WG="${NFQWS_OPT_DESYNC_WG:---payload wireguard_initiation --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
|
||||
|
||||
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=0x9c&&0>>22&0x3C@8=0x01000000" "$f 44>>16=0x9c&&48=0x01000000" $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
|
||||
}
|
||||
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,7 +281,7 @@ 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
|
||||
@@ -290,7 +290,7 @@ 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 +298,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 +317,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 +340,7 @@ 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 : 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
|
||||
@@ -351,7 +351,7 @@ function fake(ctx, desync)
|
||||
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
|
||||
@@ -371,7 +371,7 @@ end
|
||||
-- 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)
|
||||
@@ -416,16 +416,58 @@ 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 = desync.arg.seqovl_pattern and blob(desync,desync.arg.seqovl_pattern) or "\x00"
|
||||
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 : 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)
|
||||
@@ -440,32 +482,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 +507,59 @@ 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
|
||||
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
|
||||
@@ -491,7 +570,7 @@ end
|
||||
-- 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)
|
||||
@@ -600,11 +679,11 @@ 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 : 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)
|
||||
@@ -616,7 +695,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
|
||||
|
||||
@@ -697,7 +776,7 @@ end
|
||||
-- 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)
|
||||
@@ -709,7 +788,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
|
||||
|
||||
@@ -797,7 +876,7 @@ end
|
||||
-- arg : blob=<blob> - use this data instead of desync.dis.payload
|
||||
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)
|
||||
@@ -841,7 +920,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)
|
||||
@@ -877,7 +956,7 @@ end
|
||||
-- arg : dn=N - message starts from "dN". 2 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)
|
||||
|
||||
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
|
||||
@@ -1,8 +1,8 @@
|
||||
HEXDUMP_DLOG_MAX = HEXDUMP_DLOG_MAX or 32
|
||||
NOT3=bitnot(3)
|
||||
NOT7=bitnot(7)
|
||||
math.randomseed(os.time())
|
||||
|
||||
-- xor pid,tid,sec,nsec
|
||||
math.randomseed(bitxor(getpid(),gettid(),clock_gettime()))
|
||||
|
||||
-- basic desync function
|
||||
-- execute given lua code. "desync" is temporary set as global var to be accessible to the code
|
||||
@@ -35,8 +35,300 @@ function pktdebug(ctx, desync)
|
||||
DLOG("desync:")
|
||||
var_debug(desync)
|
||||
end
|
||||
-- basic desync function
|
||||
-- prints function args
|
||||
function argdebug(ctx, desync)
|
||||
var_debug(desync.arg)
|
||||
end
|
||||
|
||||
-- basic desync function
|
||||
-- prints conntrack positions to DLOG
|
||||
function posdebug(ctx, desync)
|
||||
if not desync.track then
|
||||
DLOG("posdebug: no track")
|
||||
return
|
||||
end
|
||||
local s="posdebug: "..(desync.outgoing and "out" or "in").." time +"..desync.track.pos.dt.."s direct"
|
||||
for i,pos in pairs({'n','d','b','s','p'}) do
|
||||
s=s.." "..pos..pos_get(desync, pos, false)
|
||||
end
|
||||
s=s.." reverse"
|
||||
for i,pos in pairs({'n','d','b','s','p'}) do
|
||||
s=s.." "..pos..pos_get(desync, pos, true)
|
||||
end
|
||||
s=s.." payload "..#desync.dis.payload
|
||||
if desync.reasm_data then
|
||||
s=s.." reasm "..#desync.reasm_data
|
||||
end
|
||||
if desync.decrypt_data then
|
||||
s=s.." decrypt "..#desync.decrypt_data
|
||||
end
|
||||
if desync.replay_piece_count then
|
||||
s=s.." replay "..desync.replay_piece.."/"..desync.replay_piece_count
|
||||
end
|
||||
DLOG(s)
|
||||
end
|
||||
|
||||
-- basic desync function
|
||||
-- set l7payload to 'arg.payload' if reasm.data or desync.dis.payload contains 'arg.pattern' substring
|
||||
-- NOTE : this does not set payload on C code side !
|
||||
-- NOTE : C code will not see payload change. --payload args take only payloads known to C code and cause error if unknown.
|
||||
-- arg: pattern - substring for search inside reasm_data or desync.dis.payload
|
||||
-- arg: payload - set desync.l7payload to this if detected
|
||||
-- arg: undetected - set desync.l7payload to this if not detected
|
||||
-- test case : --lua-desync=detect_payload_str:pattern=1234:payload=my --lua-desync=fake:blob=0x1234:payload=my
|
||||
function detect_payload_str(ctx, desync)
|
||||
if not desync.arg.pattern then
|
||||
error("detect_payload_str: missing 'pattern'")
|
||||
end
|
||||
local data = desync.reasm_data or desync.dis.payload
|
||||
local b = string.find(data,desync.arg.pattern,1,true)
|
||||
if b then
|
||||
DLOG("detect_payload_str: detected '"..desync.arg.payload.."'")
|
||||
if desync.arg.payload then desync.l7payload = desync.arg.payload end
|
||||
else
|
||||
DLOG("detect_payload_str: not detected '"..desync.arg.payload.."'")
|
||||
if desync.arg.undetected then desync.l7payload = desync.arg.undetected end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- this shim is needed then function is orchestrated. ctx services not available
|
||||
-- have to emulate cutoff in LUA using connection persistent table track.lua_state
|
||||
function instance_cutoff_shim(ctx, desync, dir)
|
||||
if ctx then
|
||||
instance_cutoff(ctx, dir)
|
||||
elseif not desync.track then
|
||||
DLOG("instance_cutoff_shim: cannot cutoff '"..desync.func_instance.."' because conntrack is absent")
|
||||
else
|
||||
if not desync.track.lua_state.cutoff_shim then
|
||||
desync.track.lua_state.cutoff_shim = {}
|
||||
end
|
||||
if not desync.track.lua_state.cutoff_shim[desync.func_instance] then
|
||||
desync.track.lua_state.cutoff_shim[desync.func_instance] = {}
|
||||
end
|
||||
if type(dir)=="nil" then
|
||||
-- cutoff both directions by default
|
||||
desync.track.lua_state.cutoff_shim[desync.func_instance][true] = true
|
||||
desync.track.lua_state.cutoff_shim[desync.func_instance][false] = true
|
||||
else
|
||||
desync.track.lua_state.cutoff_shim[desync.func_instance][dir] = true
|
||||
end
|
||||
if b_debug then DLOG("instance_cutoff_shim: cutoff '"..desync.func_instance.."' in="..tostring(type(dir)=="nil" and true or not dir).." out="..tostring(type(dir)=="nil" or dir)) end
|
||||
end
|
||||
end
|
||||
function cutoff_shim_check(desync)
|
||||
if not desync.track then
|
||||
DLOG("cutoff_shim_check: cannot check '"..desync.func_instance.."' cutoff because conntrack is absent")
|
||||
return false
|
||||
else
|
||||
local b=desync.track.lua_state.cutoff_shim and
|
||||
desync.track.lua_state.cutoff_shim[desync.func_instance] and
|
||||
desync.track.lua_state.cutoff_shim[desync.func_instance][desync.outgoing]
|
||||
if b and b_debug then
|
||||
DLOG("cutoff_shim_check: '"..desync.func_instance.."' "..(desync.outgoing and "out" or "in").." cutoff")
|
||||
end
|
||||
return b
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- applies # and $ prefixes. #var means var length, %var means var value
|
||||
function apply_arg_prefix(desync)
|
||||
for a,v in pairs(desync.arg) do
|
||||
local c = string.sub(v,1,1)
|
||||
if c=='#' then
|
||||
local blb = blob(desync,string.sub(v,2))
|
||||
desync.arg[a] = (type(blb)=='string' or type(blb)=='table') and #blb or 0
|
||||
elseif c=='%' then
|
||||
desync.arg[a] = blob(desync,string.sub(v,2))
|
||||
elseif c=='\\' then
|
||||
c = string.sub(v,2,2);
|
||||
if c=='#' or c=='%' then
|
||||
desync.arg[a] = string.sub(v,2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- copy instance identification and args from execution plan to desync table
|
||||
-- NOTE : to not lose VERDICT_MODIFY dissect changes pass original desync table
|
||||
-- NOTE : if a copy was passed and VERDICT_MODIFY returned you must copy modified dissect back to desync table or resend it and return VERDICT_DROP
|
||||
-- NOTE : args and some fields are substituted. if you need them - make a copy before calling this.
|
||||
function apply_execution_plan(desync, instance)
|
||||
desync.func = instance.func
|
||||
desync.func_n = instance.func_n
|
||||
desync.func_instance = instance.func_instance
|
||||
desync.arg = deepcopy(instance.arg)
|
||||
apply_arg_prefix(desync)
|
||||
end
|
||||
-- produce resulting verdict from 2 verdicts
|
||||
function verdict_aggregate(v1, v2)
|
||||
local v
|
||||
v1 = v1 or VERDICT_PASS
|
||||
v2 = v2 or VERDICT_PASS
|
||||
if v1==VERDICT_DROP or v2==VERDICT_DROP then
|
||||
v=VERDICT_DROP
|
||||
elseif v1==VERDICT_MODIFY or v2==VERDICT_MODIFY then
|
||||
v=VERDICT_MODIFY
|
||||
else
|
||||
v=VERDICT_PASS
|
||||
end
|
||||
return v
|
||||
end
|
||||
function plan_instance_execute(desync, verdict, instance)
|
||||
apply_execution_plan(desync, instance)
|
||||
if cutoff_shim_check(desync) then
|
||||
DLOG("plan_instance_execute: not calling '"..desync.func_instance.."' because of voluntary cutoff")
|
||||
elseif not payload_match_filter(desync.l7payload, instance.payload_filter) then
|
||||
DLOG("plan_instance_execute: not calling '"..desync.func_instance.."' because payload '"..desync.l7payload.."' does not match filter '"..instance.payload_filter.."'")
|
||||
elseif not pos_check_range(desync, instance.range) then
|
||||
DLOG("plan_instance_execute: not calling '"..desync.func_instance.."' because pos "..pos_str(desync,instance.range.from).." "..pos_str(desync,instance.range.to).." is out of range '"..pos_range_str(instance.range).."'")
|
||||
else
|
||||
DLOG("plan_instance_execute: calling '"..desync.func_instance.."'")
|
||||
verdict = verdict_aggregate(verdict,_G[instance.func](nil, desync))
|
||||
end
|
||||
return verdict
|
||||
end
|
||||
function plan_instance_pop(desync)
|
||||
return (desync.plan and #desync.plan>0) and table.remove(desync.plan, 1) or nil
|
||||
end
|
||||
function plan_clear(desync)
|
||||
while table.remove(desync.plan) do end
|
||||
end
|
||||
-- this approach allows nested orchestrators
|
||||
function orchestrate(ctx, desync)
|
||||
if not desync.plan then
|
||||
execution_plan_cancel(ctx)
|
||||
desync.plan = execution_plan(ctx)
|
||||
end
|
||||
end
|
||||
-- copy desync preserving lua_state
|
||||
function desync_copy(desync)
|
||||
local dcopy = deepcopy(desync)
|
||||
if desync.track then
|
||||
-- preserve lua state
|
||||
dcopy.track.lua_state = desync.track.lua_state
|
||||
end
|
||||
if desync.plan then
|
||||
-- preserve execution plan
|
||||
dcopy.plan = desync.plan
|
||||
end
|
||||
return dcopy
|
||||
end
|
||||
-- redo what whould be done without orchestration
|
||||
function replay_execution_plan(desync)
|
||||
local verdict = VERDICT_PASS
|
||||
while true do
|
||||
local instance = plan_instance_pop(desync)
|
||||
if not instance then break end
|
||||
verdict = plan_instance_execute(desync, verdict, instance)
|
||||
end
|
||||
return verdict
|
||||
end
|
||||
-- this function demonstrates how to stop execution of upcoming desync instances and take over their job
|
||||
-- this can be used, for example, for orchestrating conditional processing without modifying of desync functions code
|
||||
-- test case : --lua-desync=desync_orchestrator_example --lua-desync=pass --lua-desync=pass
|
||||
function desync_orchestrator_example(ctx, desync)
|
||||
DLOG("orchestrator: taking over upcoming desync instances")
|
||||
orchestrate(ctx, desync)
|
||||
return replay_execution_plan(desync)
|
||||
end
|
||||
|
||||
-- if seq is over 2G s and p position comparision can be wrong
|
||||
function pos_counter_overflow(desync, mode, reverse)
|
||||
if not desync.track or not desync.track.tcp or (mode~='s' and mode~='p') then return false end
|
||||
local track_pos = reverse and desync.track.pos.reverse or desync.track.pos.direct
|
||||
return track_pos.tcp.rseq_over_2G
|
||||
end
|
||||
-- these functions duplicate range check logic from C code
|
||||
-- mode must be n,d,b,s,x,a
|
||||
-- pos is {mode,pos}
|
||||
-- range is {from={mode,pos}, to={mode,pos}, upper_cutoff}
|
||||
-- upper_cutoff = true means non-inclusive upper boundary
|
||||
function pos_get_pos(track_pos, mode)
|
||||
if track_pos then
|
||||
if mode=='n' then
|
||||
return track_pos.pcounter
|
||||
elseif mode=='d' then
|
||||
return track_pos.pdcounter
|
||||
elseif mode=='b' then
|
||||
return track_pos.pbcounter
|
||||
elseif track_pos.tcp then
|
||||
if mode=='s' then
|
||||
return track_pos.tcp.rseq
|
||||
elseif mode=='p' then
|
||||
return track_pos.tcp.pos
|
||||
end
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
function pos_get(desync, mode, reverse)
|
||||
if desync.track then
|
||||
local track_pos = reverse and desync.track.pos.reverse or desync.track.pos.direct
|
||||
return pos_get_pos(track_pos,mode)
|
||||
end
|
||||
return 0
|
||||
end
|
||||
function pos_check_from(desync, range)
|
||||
if range.from.mode == 'x' or pos_counter_overflow(desync, range.from.mode) then return false end
|
||||
if range.from.mode ~= 'a' then
|
||||
if desync.track then
|
||||
return pos_get(desync, range.from.mode) >= range.from.pos
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true;
|
||||
end
|
||||
function pos_check_to(desync, range)
|
||||
local ps
|
||||
if range.to.mode == 'x' or pos_counter_overflow(desync, range.to.mode) then return false end
|
||||
if range.to.mode ~= 'a' then
|
||||
if desync.track then
|
||||
ps = pos_get(desync, range.to.mode)
|
||||
return (ps < range.to.pos) or not range.upper_cutoff and (ps == range.to.pos)
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true;
|
||||
end
|
||||
function pos_check_range(desync, range)
|
||||
return pos_check_from(desync,range) and pos_check_to(desync,range)
|
||||
end
|
||||
function pos_range_str(range)
|
||||
return range.from.mode..range.from.pos..(range.upper_cutoff and '<' or '-')..range.to.mode..range.to.pos
|
||||
end
|
||||
function pos_str(desync, pos)
|
||||
return pos.mode..pos_get(desync, pos.mode)
|
||||
end
|
||||
|
||||
-- sequence comparision functions. they work only within 2G interval
|
||||
-- seq1>=seq2
|
||||
function seq_ge(seq1, seq2)
|
||||
return 0==bitand(u32add(seq1, -seq2), 0x80000000)
|
||||
end
|
||||
-- seq1>seq2
|
||||
function seq_gt(seq1, seq2)
|
||||
return seq1~=seq2 and seq_ge(seq1, seq2)
|
||||
end
|
||||
-- seq1<seq2
|
||||
function seq_lt(seq1, seq2)
|
||||
return 0~=bitand(u32add(seq1, -seq2), 0x80000000)
|
||||
end
|
||||
-- seq1<=seq2
|
||||
function seq_le(seq1, seq2)
|
||||
return seq1==seq2 or 0~=bitand(u32add(seq1, -seq2), 0x80000000)
|
||||
end
|
||||
-- seq_low<=seq<=seq_hi
|
||||
function seq_within(seq, seq_low, seq_hi)
|
||||
return seq_ge(seq, seq_low) and seq_le(seq, seq_hi)
|
||||
end
|
||||
|
||||
function is_retransmission(desync)
|
||||
return desync.track and desync.track.pos.direct.tcp and seq_ge(desync.track.pos.direct.tcp.uppos_prev, desync.track.pos.direct.tcp.pos)
|
||||
end
|
||||
|
||||
-- prepare standard rawsend options from desync
|
||||
-- repeats - how many time send the packet
|
||||
@@ -108,12 +400,15 @@ function str_or_hex(s)
|
||||
return s
|
||||
end
|
||||
end
|
||||
function logical_xor(a,b)
|
||||
return a and not b or not a and b
|
||||
end
|
||||
-- print to DLOG any variable. tables are expanded in the tree form, unprintables strings are hex dumped
|
||||
function var_debug(v)
|
||||
local function dbg(v,level)
|
||||
if type(v)=="table" then
|
||||
for key, value in pairs(v) do
|
||||
DLOG(string.rep(" ",2*level).."."..key)
|
||||
DLOG(string.rep(" ",2*level).."."..tostring(key))
|
||||
dbg(v[key],level+1)
|
||||
end
|
||||
elseif type(v)=="string" then
|
||||
@@ -301,6 +596,88 @@ function http_dissect_req(http)
|
||||
local uri = string.sub(req,pos,pnext-1)
|
||||
return { method = method, uri = uri, headers = http_dissect_headers(http,hdrpos) }
|
||||
end
|
||||
function http_dissect_reply(http)
|
||||
if not http then return nil; end
|
||||
local s, pos, code
|
||||
s = string.sub(http,1,8)
|
||||
if s~="HTTP/1.1" and s~="HTTP/1.0" then return nil end
|
||||
pos = string.find(http,"[ \t\r\n]",10)
|
||||
code = tonumber(string.sub(http,10,pos-1))
|
||||
if not code then return nil end
|
||||
pos = find_next_line(http,pos)
|
||||
return { code = code, headers = http_dissect_headers(http,pos) }
|
||||
end
|
||||
function dissect_url(url)
|
||||
local p1,pb,pstart,pend
|
||||
local proto, creds, domain, port, uri
|
||||
p1 = string.find(url,"[^ \t]")
|
||||
if not p1 then return nil end
|
||||
pb = p1
|
||||
pstart,pend = string.find(url,"[a-z]+://",p1)
|
||||
if pend then
|
||||
proto = string.sub(url,pstart,pend-3)
|
||||
p1 = pend+1
|
||||
end
|
||||
pstart,pend = string.find(url,"[@/]",p1)
|
||||
if pend and string.sub(url,pstart,pend)=='@' then
|
||||
creds = string.sub(url,p1,pend-1)
|
||||
p1 = pend+1
|
||||
end
|
||||
pstart,pend = string.find(url,"/",p1,true)
|
||||
if pend then
|
||||
if pend==pb then
|
||||
uri = string.sub(url,pb)
|
||||
else
|
||||
uri = string.sub(url,pend)
|
||||
domain = string.sub(url,p1,pend-1)
|
||||
end
|
||||
else
|
||||
if proto then
|
||||
domain = string.sub(url,p1)
|
||||
else
|
||||
uri = string.sub(url,p1)
|
||||
end
|
||||
end
|
||||
if domain then
|
||||
pstart,pend = string.find(domain,':',1,true)
|
||||
if pend then
|
||||
port = string.sub(domain, pend+1)
|
||||
domain = string.sub(domain, 1, pstart-1)
|
||||
end
|
||||
end
|
||||
return { proto = proto, creds = creds, domain = domain, port = port, uri=uri }
|
||||
end
|
||||
function dissect_nld(domain, level)
|
||||
if domain then
|
||||
local n=1
|
||||
for pos=#domain,1,-1 do
|
||||
if string.sub(domain,pos,pos)=='.' then
|
||||
if n==level then
|
||||
return string.sub(domain, pos+1)
|
||||
end
|
||||
n=n+1
|
||||
end
|
||||
end
|
||||
if n==level then
|
||||
return domain
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- support sni=%var
|
||||
function tls_mod_shim(desync, blob, modlist, payload)
|
||||
local p1,p2 = string.find(modlist,"sni=%%[^,]+")
|
||||
if p1 then
|
||||
local var = string.sub(modlist,p1+5,p2)
|
||||
local val = desync[var] or _G[var]
|
||||
if not val then
|
||||
error("tls_mod_shim: non-existent var '"..var.."'")
|
||||
end
|
||||
modlist = string.sub(modlist,1,p1+3)..val..string.sub(modlist,p2+1)
|
||||
end
|
||||
return tls_mod(blob,modlist,payload)
|
||||
end
|
||||
|
||||
-- convert comma separated list of tcp flags to tcp.th_flags bit field
|
||||
function parse_tcp_flags(s)
|
||||
@@ -385,6 +762,22 @@ function fix_ip6_next(ip6, last_proto)
|
||||
end
|
||||
end
|
||||
|
||||
-- reverses ip addresses, ports and seq/ack
|
||||
function dis_reverse(dis)
|
||||
if dis.ip then
|
||||
dis.ip.ip_src, dis.ip.ip_dst = dis.ip.ip_dst, dis.ip.ip_src
|
||||
end
|
||||
if dis.ip6 then
|
||||
dis.ip6.ip6_src, dis.ip6.ip6_dst = dis.ip6.ip6_dst, dis.ip6.ip6_src
|
||||
end
|
||||
if dis.tcp then
|
||||
dis.tcp.th_sport, dis.tcp.th_dport = dis.tcp.th_dport, dis.tcp.th_sport
|
||||
dis.tcp.th_ack, dis.tcp.th_seq = dis.tcp.th_seq, dis.tcp.th_ack
|
||||
end
|
||||
if dis.udp then
|
||||
dis.udp.uh_sport, dis.udp.uh_dport = dis.udp.uh_dport, dis.udp.uh_sport
|
||||
end
|
||||
end
|
||||
|
||||
-- parse autottl : delta,min-max
|
||||
function parse_autottl(s)
|
||||
@@ -453,6 +846,7 @@ end
|
||||
-- ip6_hopbyhop[=hex] - add hopbyhop ipv6 header with optional data. data size must be 6+N*8. all zero by default.
|
||||
-- ip6_hopbyhop2[=hex] - add second hopbyhop ipv6 header with optional data. data size must be 6+N*8. all zero by default.
|
||||
-- ip6_destopt[=hex] - add destopt ipv6 header with optional data. data size must be 6+N*8. all zero by default.
|
||||
-- ip6_destopt2[=hex] - add second destopt ipv6 header with optional data. data size must be 6+N*8. all zero by default.
|
||||
-- ip6_routing[=hex] - add routing ipv6 header with optional data. data size must be 6+N*8. all zero by default.
|
||||
-- ip6_ah[=hex] - add authentication ipv6 header with optional data. data size must be 6+N*4. 0000 + 4 random bytes by default.
|
||||
|
||||
@@ -513,10 +907,10 @@ function apply_fooling(desync, dis, fooling_options)
|
||||
if not dis then dis = desync.dis end
|
||||
if dis.tcp then
|
||||
if tonumber(fooling_options.tcp_seq) then
|
||||
dis.tcp.th_seq = dis.tcp.th_seq + fooling_options.tcp_seq
|
||||
dis.tcp.th_seq = u32add(dis.tcp.th_seq, fooling_options.tcp_seq)
|
||||
end
|
||||
if tonumber(fooling_options.tcp_ack) then
|
||||
dis.tcp.th_ack = dis.tcp.th_ack + fooling_options.tcp_ack
|
||||
dis.tcp.th_ack = u32add(dis.tcp.th_ack, fooling_options.tcp_ack)
|
||||
end
|
||||
if fooling_options.tcp_flags_unset then
|
||||
dis.tcp.th_flags = bitand(dis.tcp.th_flags, bitnot(parse_tcp_flags(fooling_options.tcp_flags_unset)))
|
||||
@@ -527,7 +921,7 @@ function apply_fooling(desync, dis, fooling_options)
|
||||
if tonumber(fooling_options.tcp_ts) then
|
||||
local idx = find_tcp_option(dis.tcp.options,TCP_KIND_TS)
|
||||
if idx and (dis.tcp.options[idx].data and #dis.tcp.options[idx].data or 0)==8 then
|
||||
dis.tcp.options[idx].data = bu32(u32(dis.tcp.options[idx].data)+fooling_options.tcp_ts)..string.sub(dis.tcp.options[idx].data,5)
|
||||
dis.tcp.options[idx].data = bu32(u32add(u32(dis.tcp.options[idx].data),fooling_options.tcp_ts))..string.sub(dis.tcp.options[idx].data,5)
|
||||
else
|
||||
DLOG("apply_fooling: timestamp tcp option not present or invalid")
|
||||
end
|
||||
@@ -744,7 +1138,6 @@ end
|
||||
-- send dissect with tcp segmentation based on mss value. appply specified rawsend options.
|
||||
function rawsend_dissect_segmented(desync, dis, mss, options)
|
||||
local discopy = deepcopy(dis)
|
||||
apply_ip_id(desync, discopy, options and options.ipid)
|
||||
apply_fooling(desync, discopy, options and options.fooling)
|
||||
|
||||
if dis.tcp then
|
||||
@@ -760,6 +1153,7 @@ function rawsend_dissect_segmented(desync, dis, mss, options)
|
||||
len = #payload - pos + 1
|
||||
if len > max_data then len = max_data end
|
||||
discopy.payload = string.sub(payload,pos,pos+len-1)
|
||||
apply_ip_id(desync, discopy, options and options.ipid)
|
||||
if not rawsend_dissect_ipfrag(discopy, options) then
|
||||
-- stop if failed
|
||||
return false
|
||||
@@ -770,6 +1164,7 @@ function rawsend_dissect_segmented(desync, dis, mss, options)
|
||||
return true
|
||||
end
|
||||
end
|
||||
apply_ip_id(desync, discopy, options and options.ipid)
|
||||
-- no reason to segment
|
||||
return rawsend_dissect_ipfrag(discopy, options)
|
||||
end
|
||||
@@ -796,23 +1191,27 @@ function direction_cutoff_opposite(ctx, desync, def)
|
||||
local dir = desync.arg.dir or def or "out"
|
||||
if dir=="out" then
|
||||
-- cutoff in
|
||||
instance_cutoff(ctx, false)
|
||||
instance_cutoff_shim(ctx, desync, false)
|
||||
elseif dir=="in" then
|
||||
-- cutoff out
|
||||
instance_cutoff(ctx, true)
|
||||
instance_cutoff_shim(ctx, desync, true)
|
||||
end
|
||||
end
|
||||
|
||||
-- return true if l7payload matches filter l7payload_filter - comma separated list of payload types
|
||||
function payload_match_filter(l7payload, l7payload_filter, def)
|
||||
local argpl = l7payload_filter or def or "known"
|
||||
local neg = string.sub(argpl,1,1)=="~"
|
||||
local pl = neg and string.sub(argpl,2) or argpl
|
||||
return neg ~= (in_list(pl, "all") or in_list(pl, l7payload) or in_list(pl, "known") and l7payload~="unknown" and l7payload~="empty")
|
||||
end
|
||||
-- check if desync payload type comply with payload type list in arg.payload
|
||||
-- if arg.payload is not present - check for known payload - not empty and not unknown (nfqws1 behavior without "--desync-any-protocol" option)
|
||||
-- if arg.payload is prefixed with '~' - it means negation
|
||||
function payload_check(desync, def)
|
||||
local b
|
||||
local argpl = desync.arg.payload or def or "known"
|
||||
local neg = string.sub(argpl,1,1)=="~"
|
||||
local pl = neg and string.sub(argpl,2) or argpl
|
||||
|
||||
b = neg ~= (in_list(pl, "all") or in_list(pl, desync.l7payload) or in_list(pl, "known") and desync.l7payload~="unknown" and desync.l7payload~="empty")
|
||||
if not b then
|
||||
local b = payload_match_filter(desync.l7payload, desync.arg.payload, def)
|
||||
if not b and b_debug then
|
||||
local argpl = desync.arg.payload or def or "known"
|
||||
DLOG("payload_check: payload '"..desync.l7payload.."' does not pass '"..argpl.."' filter")
|
||||
end
|
||||
return b
|
||||
@@ -883,6 +1282,18 @@ function genhost(len, template)
|
||||
end
|
||||
end
|
||||
|
||||
-- return ip addr of target host in text form
|
||||
function host_ip(desync)
|
||||
return desync.target.ip and ntop(desync.target.ip) or desync.target.ip6 and ntop(desync.target.ip6)
|
||||
end
|
||||
-- return hostname of target host if present or ip address in text form otherwise
|
||||
function host_or_ip(desync)
|
||||
if desync.track and desync.track.hostname then
|
||||
return desync.track.hostname
|
||||
end
|
||||
return host_ip(desync)
|
||||
end
|
||||
|
||||
function is_absolute_path(path)
|
||||
if string.sub(path,1,1)=='/' then return true end
|
||||
local un = uname()
|
||||
@@ -905,7 +1316,7 @@ function wsize_rewrite(dis, arg)
|
||||
local b = false
|
||||
if arg.wsize then
|
||||
local wsize = tonumber(arg.wsize)
|
||||
DLOG("window size "..dis.tcp.th_win.." => "..wsize)
|
||||
DLOG("wsize_rewrite: window size "..dis.tcp.th_win.." => "..wsize)
|
||||
dis.tcp.th_win = tonumber(arg.wsize)
|
||||
b = true
|
||||
end
|
||||
@@ -915,9 +1326,9 @@ function wsize_rewrite(dis, arg)
|
||||
if i then
|
||||
local oldscale = u8(dis.tcp.options[i].data)
|
||||
if scale>oldscale then
|
||||
DLOG("not increasing scale factor")
|
||||
DLOG("wsize_rewrite: not increasing scale factor")
|
||||
elseif scale<oldscale then
|
||||
DLOG("scale factor "..oldscale.." => "..scale)
|
||||
DLOG("wsize_rewrite: scale factor "..oldscale.." => "..scale)
|
||||
dis.tcp.options[i].data = bu8(scale)
|
||||
b = true
|
||||
end
|
||||
@@ -1031,4 +1442,3 @@ function ipfrag2(dis, ipfrag_options)
|
||||
|
||||
return {dis1,dis2}
|
||||
end
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ function pcap_write_packet(file, raw)
|
||||
local sec, nsec = clock_gettime();
|
||||
file:write(bu32(sec)..bu32(nsec)..bu32(#raw)..bu32(#raw))
|
||||
file:write(raw)
|
||||
file:close()
|
||||
end
|
||||
function pcap_write(file, raw)
|
||||
local pos = file:seek()
|
||||
@@ -16,7 +15,7 @@ function pcap_write(file, raw)
|
||||
pcap_write_packet(file, raw)
|
||||
end
|
||||
|
||||
-- test case : nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-init=@zapret-pcap.lua --writeable=zdir --in-range=a --lua-desync=pcap:file=test.pcap
|
||||
-- test case : --writeable=zdir --in-range=a --lua-desync=pcap:file=test.pcap
|
||||
-- arg : file=<filename> - file for storing pcap data. if --writeable is specified and filename is relative - append filename to writeable path
|
||||
-- arg : keep - do not overwrite file, append packets to existing
|
||||
function pcap(ctx, desync)
|
||||
@@ -36,4 +35,5 @@ function pcap(ctx, desync)
|
||||
error("pcap: could not write to '".._G[fn_cache_name].."'")
|
||||
end
|
||||
pcap_write(f, raw_packet(ctx))
|
||||
f:close()
|
||||
end
|
||||
|
||||
@@ -264,8 +264,8 @@ end
|
||||
function test_bit()
|
||||
local v, v2, v3, v4, b1, b2, pow
|
||||
|
||||
v = math.random(0,0xFFFFFFFFFFFF)
|
||||
b1 = math.random(1,15)
|
||||
v = math.random(0,0xFFFFFFFF)
|
||||
b1 = math.random(1,16)
|
||||
|
||||
v2 = bitrshift(v, b1)
|
||||
pow = 2^b1
|
||||
@@ -275,17 +275,17 @@ function test_bit()
|
||||
|
||||
v2 = bitlshift(v, b1)
|
||||
pow = 2^b1
|
||||
v3 = v * pow
|
||||
print(string.format("lshift(0x%X,%u) = 0x%X 0x%X*%u = 0x%X", v,b1,v2, v,pow,v3))
|
||||
v3 = (v * pow) % 0x100000000
|
||||
print(string.format("lshift(0x%X,%u) = 0x%X 0x%X*%u %% 0x10000000 = 0x%X", v,b1,v2, v,pow,v3))
|
||||
test_assert(v2==v3)
|
||||
|
||||
v2 = math.random(0,0xFFFFFFFFFFFF)
|
||||
v2 = math.random(0,0xFFFFFFFF)
|
||||
v3 = bitxor(v, v2)
|
||||
v4 = bitor(v, v2) - bitand(v, v2)
|
||||
print(string.format("xor(0x%X,0x%X) = %X or/and/minus = %X", v, v2, v3, v4))
|
||||
test_assert(v3==v4)
|
||||
|
||||
b2 = b1 + math.random(1,31)
|
||||
b2 = b1 + math.random(1,15)
|
||||
v2 = bitget(v, b1, b2)
|
||||
pow = 2^(b2-b1+1) - 1
|
||||
v3 = bitand(bitrshift(v,b1), pow)
|
||||
@@ -299,8 +299,32 @@ function test_bit()
|
||||
test_assert(v2==v3)
|
||||
end
|
||||
|
||||
function test_ux()
|
||||
local v1, v2, v3, usum, sum
|
||||
for k,test in pairs({
|
||||
{ add=u8add, fname="u8add", max = 0xFF },
|
||||
{ add=u16add, fname="u16add", max = 0xFFFF },
|
||||
{ add=u24add, fname="u24add", max = 0xFFFFFF },
|
||||
{ add=u32add, fname="u32add", max = 0xFFFFFFFF }
|
||||
}) do
|
||||
io.write(test.fname.." : ")
|
||||
for i=1,1000 do
|
||||
v1=math.random(-test.max,test.max)
|
||||
v2=math.random(-test.max,test.max)
|
||||
v3=math.random(-test.max,test.max)
|
||||
usum = test.add(v1,v2,v3)
|
||||
sum = bitand((v1+v2+v3)%(test.max+1),test.max)
|
||||
if sum~=usum then
|
||||
print("FAIL")
|
||||
end
|
||||
test_assert(sum==usum)
|
||||
end
|
||||
print("OK")
|
||||
end
|
||||
end
|
||||
|
||||
function test_bin(...)
|
||||
test_run({test_ub, test_bit},...)
|
||||
test_run({test_ub, test_bit, test_ux},...)
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
-- test case : nfqws2 --qnum 200 --debug --lua-init=@zapret-wgobfs.lua --in-range=a --out-range=a --lua-desync=wgobfs:secret=mycoolpassword
|
||||
-- test case : --in-range=a --out-range=a --lua-desync=wgobfs:secret=mycoolpassword
|
||||
-- encrypt standard wireguard messages - initiation, response, cookie - and change udp packet size
|
||||
-- do not encrypt data messages and keepalives
|
||||
-- wgobfs adds maximum of 30+padmax bytes to udp size
|
||||
|
||||
@@ -2,64 +2,65 @@
|
||||
#include "checksum.h"
|
||||
#include <netinet/in.h>
|
||||
|
||||
//#define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
|
||||
//#define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
|
||||
// #define htonll(x) ((1==htonl(1)) ? (x) : ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
|
||||
// #define ntohll(x) ((1==ntohl(1)) ? (x) : ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
|
||||
|
||||
static uint16_t from64to16(uint64_t x)
|
||||
{
|
||||
uint32_t u = (uint32_t)(uint16_t)x + (uint16_t)(x>>16) + (uint16_t)(x>>32) + (uint16_t)(x>>48);
|
||||
return (uint16_t)u + (uint16_t)(u>>16);
|
||||
uint32_t u = (uint32_t)(uint16_t)x + (uint16_t)(x >> 16) + (uint16_t)(x >> 32) + (uint16_t)(x >> 48);
|
||||
return (uint16_t)u + (uint16_t)(u >> 16);
|
||||
}
|
||||
|
||||
// this function preserves data alignment requirements (otherwise it will be damn slow on mips arch)
|
||||
// and uses 64-bit arithmetics to improve speed
|
||||
// taken from linux source code
|
||||
static uint16_t do_csum(const uint8_t * buff, size_t len)
|
||||
static uint16_t do_csum(const uint8_t *buff, size_t len)
|
||||
{
|
||||
uint8_t odd;
|
||||
size_t count;
|
||||
uint64_t result,w,carry=0;
|
||||
uint64_t result, w, carry = 0;
|
||||
uint16_t u16;
|
||||
|
||||
if (!len) return 0;
|
||||
if (!len)
|
||||
return 0;
|
||||
odd = (uint8_t)(1 & (size_t)buff);
|
||||
if (odd)
|
||||
{
|
||||
// any endian compatible
|
||||
u16 = 0;
|
||||
*((uint8_t*)&u16+1) = *buff;
|
||||
*((uint8_t *)&u16 + 1) = *buff;
|
||||
result = u16;
|
||||
len--;
|
||||
buff++;
|
||||
}
|
||||
else
|
||||
result = 0;
|
||||
count = len >> 1; /* nr of 16-bit words.. */
|
||||
count = len >> 1; /* nr of 16-bit words.. */
|
||||
if (count)
|
||||
{
|
||||
if (2 & (size_t) buff)
|
||||
if (2 & (size_t)buff)
|
||||
{
|
||||
result += *(uint16_t *) buff;
|
||||
result += *(uint16_t *)buff;
|
||||
count--;
|
||||
len -= 2;
|
||||
buff += 2;
|
||||
}
|
||||
count >>= 1; /* nr of 32-bit words.. */
|
||||
count >>= 1; /* nr of 32-bit words.. */
|
||||
if (count)
|
||||
{
|
||||
if (4 & (size_t) buff)
|
||||
if (4 & (size_t)buff)
|
||||
{
|
||||
result += *(uint32_t *) buff;
|
||||
result += *(uint32_t *)buff;
|
||||
count--;
|
||||
len -= 4;
|
||||
buff += 4;
|
||||
}
|
||||
count >>= 1; /* nr of 64-bit words.. */
|
||||
count >>= 1; /* nr of 64-bit words.. */
|
||||
if (count)
|
||||
{
|
||||
do
|
||||
{
|
||||
w = *(uint64_t *) buff;
|
||||
w = *(uint64_t *)buff;
|
||||
count--;
|
||||
buff += 8;
|
||||
result += carry;
|
||||
@@ -71,13 +72,13 @@ static uint16_t do_csum(const uint8_t * buff, size_t len)
|
||||
}
|
||||
if (len & 4)
|
||||
{
|
||||
result += *(uint32_t *) buff;
|
||||
result += *(uint32_t *)buff;
|
||||
buff += 4;
|
||||
}
|
||||
}
|
||||
if (len & 2)
|
||||
{
|
||||
result += *(uint16_t *) buff;
|
||||
result += *(uint16_t *)buff;
|
||||
buff += 2;
|
||||
}
|
||||
}
|
||||
@@ -85,54 +86,54 @@ static uint16_t do_csum(const uint8_t * buff, size_t len)
|
||||
{
|
||||
// any endian compatible
|
||||
u16 = 0;
|
||||
*(uint8_t*)&u16 = *buff;
|
||||
*(uint8_t *)&u16 = *buff;
|
||||
result += u16;
|
||||
}
|
||||
u16 = from64to16(result);
|
||||
if (odd) u16 = ((u16 >> 8) & 0xff) | ((u16 & 0xff) << 8);
|
||||
if (odd)
|
||||
u16 = ((u16 >> 8) & 0xff) | ((u16 & 0xff) << 8);
|
||||
return u16;
|
||||
}
|
||||
|
||||
uint16_t csum_partial(const void *buff, size_t len)
|
||||
{
|
||||
return do_csum(buff,len);
|
||||
return do_csum(buff, len);
|
||||
}
|
||||
|
||||
uint16_t csum_tcpudp_magic(uint32_t saddr, uint32_t daddr, size_t len, uint8_t proto, uint16_t sum)
|
||||
{
|
||||
return ~from64to16((uint64_t)saddr + daddr + sum + htonl(len+proto));
|
||||
return ~from64to16((uint64_t)saddr + daddr + sum + htonl(len + proto));
|
||||
}
|
||||
|
||||
uint16_t ip4_compute_csum(const void *buff, size_t len)
|
||||
{
|
||||
return ~from64to16(do_csum(buff,len));
|
||||
return ~from64to16(do_csum(buff, len));
|
||||
}
|
||||
void ip4_fix_checksum(struct ip *ip)
|
||||
{
|
||||
ip->ip_sum = 0;
|
||||
ip->ip_sum = ip4_compute_csum(ip, ip->ip_hl<<2);
|
||||
ip->ip_sum = ip4_compute_csum(ip, ip->ip_hl << 2);
|
||||
}
|
||||
|
||||
uint16_t csum_ipv6_magic(const void *saddr, const void *daddr, size_t len, uint8_t proto, uint16_t sum)
|
||||
{
|
||||
uint64_t a = (uint64_t)sum + htonl(len+proto) +
|
||||
*(uint32_t*)saddr + *((uint32_t*)saddr+1) + *((uint32_t*)saddr+2) + *((uint32_t*)saddr+3) +
|
||||
*(uint32_t*)daddr + *((uint32_t*)daddr+1) + *((uint32_t*)daddr+2) + *((uint32_t*)daddr+3);
|
||||
uint64_t a = (uint64_t)sum + htonl(len + proto) +
|
||||
*(uint32_t *)saddr + *((uint32_t *)saddr + 1) + *((uint32_t *)saddr + 2) + *((uint32_t *)saddr + 3) +
|
||||
*(uint32_t *)daddr + *((uint32_t *)daddr + 1) + *((uint32_t *)daddr + 2) + *((uint32_t *)daddr + 3);
|
||||
return ~from64to16(a);
|
||||
}
|
||||
|
||||
|
||||
void tcp4_fix_checksum(struct tcphdr *tcp,size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr)
|
||||
void tcp4_fix_checksum(struct tcphdr *tcp, size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr)
|
||||
{
|
||||
tcp->th_sum = 0;
|
||||
tcp->th_sum = csum_tcpudp_magic(src_addr->s_addr,dest_addr->s_addr,len,IPPROTO_TCP,csum_partial(tcp,len));
|
||||
tcp->th_sum = csum_tcpudp_magic(src_addr->s_addr, dest_addr->s_addr, len, IPPROTO_TCP, csum_partial(tcp, len));
|
||||
}
|
||||
void tcp6_fix_checksum(struct tcphdr *tcp,size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
|
||||
void tcp6_fix_checksum(struct tcphdr *tcp, size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
|
||||
{
|
||||
tcp->th_sum = 0;
|
||||
tcp->th_sum = csum_ipv6_magic(src_addr,dest_addr,len,IPPROTO_TCP,csum_partial(tcp,len));
|
||||
tcp->th_sum = csum_ipv6_magic(src_addr, dest_addr, len, IPPROTO_TCP, csum_partial(tcp, len));
|
||||
}
|
||||
void tcp_fix_checksum(struct tcphdr *tcp,size_t len,const struct ip *ip,const struct ip6_hdr *ip6hdr)
|
||||
void tcp_fix_checksum(struct tcphdr *tcp, size_t len, const struct ip *ip, const struct ip6_hdr *ip6hdr)
|
||||
{
|
||||
if (ip)
|
||||
tcp4_fix_checksum(tcp, len, &ip->ip_src, &ip->ip_dst);
|
||||
@@ -140,17 +141,17 @@ void tcp_fix_checksum(struct tcphdr *tcp,size_t len,const struct ip *ip,const st
|
||||
tcp6_fix_checksum(tcp, len, &ip6hdr->ip6_src, &ip6hdr->ip6_dst);
|
||||
}
|
||||
|
||||
void udp4_fix_checksum(struct udphdr *udp,size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr)
|
||||
void udp4_fix_checksum(struct udphdr *udp, size_t len, const struct in_addr *src_addr, const struct in_addr *dest_addr)
|
||||
{
|
||||
udp->uh_sum = 0;
|
||||
udp->uh_sum = csum_tcpudp_magic(src_addr->s_addr,dest_addr->s_addr,len,IPPROTO_UDP,csum_partial(udp,len));
|
||||
udp->uh_sum = csum_tcpudp_magic(src_addr->s_addr, dest_addr->s_addr, len, IPPROTO_UDP, csum_partial(udp, len));
|
||||
}
|
||||
void udp6_fix_checksum(struct udphdr *udp,size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
|
||||
void udp6_fix_checksum(struct udphdr *udp, size_t len, const struct in6_addr *src_addr, const struct in6_addr *dest_addr)
|
||||
{
|
||||
udp->uh_sum = 0;
|
||||
udp->uh_sum = csum_ipv6_magic(src_addr,dest_addr,len,IPPROTO_UDP,csum_partial(udp,len));
|
||||
udp->uh_sum = csum_ipv6_magic(src_addr, dest_addr, len, IPPROTO_UDP, csum_partial(udp, len));
|
||||
}
|
||||
void udp_fix_checksum(struct udphdr *udp,size_t len,const struct ip *ip,const struct ip6_hdr *ip6hdr)
|
||||
void udp_fix_checksum(struct udphdr *udp, size_t len, const struct ip *ip, const struct ip6_hdr *ip6hdr)
|
||||
{
|
||||
if (ip)
|
||||
udp4_fix_checksum(udp, len, &ip->ip_src, &ip->ip_dst);
|
||||
|
||||
257
nfq2/conntrack.c
257
nfq2/conntrack.c
@@ -37,7 +37,7 @@ void ConntrackClearHostname(t_ctrack *track)
|
||||
static void ConntrackClearTrack(t_ctrack *track)
|
||||
{
|
||||
ConntrackClearHostname(track);
|
||||
ReasmClear(&track->reasm_orig);
|
||||
ReasmClear(&track->reasm_client);
|
||||
rawpacket_queue_destroy(&track->delayed);
|
||||
luaL_unref(params.L, LUA_REGISTRYINDEX, track->lua_state);
|
||||
luaL_unref(params.L, LUA_REGISTRYINDEX, track->lua_instance_cutoff);
|
||||
@@ -70,24 +70,24 @@ void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_s
|
||||
p->pool = NULL;
|
||||
}
|
||||
|
||||
void ConntrackExtractConn(t_conn *c, bool bReverse, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr)
|
||||
void ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis)
|
||||
{
|
||||
memset(c, 0, sizeof(*c));
|
||||
if (ip)
|
||||
if (dis->ip)
|
||||
{
|
||||
c->l3proto = IPPROTO_IP;
|
||||
c->dst.ip = bReverse ? ip->ip_src : ip->ip_dst;
|
||||
c->src.ip = bReverse ? ip->ip_dst : ip->ip_src;
|
||||
c->dst.ip = bReverse ? dis->ip->ip_src : dis->ip->ip_dst;
|
||||
c->src.ip = bReverse ? dis->ip->ip_dst : dis->ip->ip_src;
|
||||
}
|
||||
else if (ip6)
|
||||
else if (dis->ip6)
|
||||
{
|
||||
c->l3proto = IPPROTO_IPV6;
|
||||
c->dst.ip6 = bReverse ? ip6->ip6_src : ip6->ip6_dst;
|
||||
c->src.ip6 = bReverse ? ip6->ip6_dst : ip6->ip6_src;
|
||||
c->dst.ip6 = bReverse ? dis->ip6->ip6_src : dis->ip6->ip6_dst;
|
||||
c->src.ip6 = bReverse ? dis->ip6->ip6_dst : dis->ip6->ip6_src;
|
||||
}
|
||||
else
|
||||
c->l3proto = -1;
|
||||
extract_ports(tcphdr, udphdr, &c->l4proto, bReverse ? &c->dport : &c->sport, bReverse ? &c->sport : &c->dport);
|
||||
extract_ports(dis->tcp, dis->udp, &c->l4proto, bReverse ? &c->dport : &c->sport, bReverse ? &c->sport : &c->dport);
|
||||
}
|
||||
|
||||
|
||||
@@ -102,8 +102,7 @@ static void ConntrackInitTrack(t_ctrack *t)
|
||||
{
|
||||
memset(t, 0, sizeof(*t));
|
||||
t->l7proto = L7_UNKNOWN;
|
||||
t->scale_orig = t->scale_reply = SCALE_NONE;
|
||||
time(&t->t_start);
|
||||
t->pos.client.scale = t->pos.server.scale = SCALE_NONE;
|
||||
rawpacket_queue_init(&t->delayed);
|
||||
lua_newtable(params.L);
|
||||
t->lua_state = luaL_ref(params.L, LUA_REGISTRYINDEX);
|
||||
@@ -128,102 +127,105 @@ static t_conntrack_pool *ConntrackNew(t_conntrack_pool **pp, const t_conn *c)
|
||||
return ctnew;
|
||||
}
|
||||
|
||||
// non-tcp packets are passed with tcphdr=NULL but len_payload filled
|
||||
static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr *tcphdr, uint32_t len_payload)
|
||||
static void ConntrackApplyPos(t_ctrack *t, bool bReverse, const struct dissect *dis)
|
||||
{
|
||||
uint8_t scale;
|
||||
uint16_t mss;
|
||||
t_ctrack_position *direct, *reverse;
|
||||
|
||||
direct = bReverse ? &t->pos.server : &t->pos.client;
|
||||
reverse = bReverse ? &t->pos.client : &t->pos.server;
|
||||
|
||||
if (dis->ip6) direct->ip6flow = ntohl(dis->ip6->ip6_ctlun.ip6_un1.ip6_un1_flow);
|
||||
|
||||
scale = tcp_find_scale_factor(dis->tcp);
|
||||
mss = ntohs(tcp_find_mss(dis->tcp));
|
||||
|
||||
direct->seq_last = ntohl(dis->tcp->th_seq);
|
||||
direct->pos = direct->seq_last + dis->len_payload;
|
||||
reverse->pos = reverse->seq_last = ntohl(dis->tcp->th_ack);
|
||||
if (t->pos.state == SYN)
|
||||
direct->uppos_prev = direct->uppos = direct->pos;
|
||||
else if (dis->len_payload)
|
||||
{
|
||||
direct->uppos_prev = direct->uppos;
|
||||
if (!((direct->pos - direct->uppos) & 0x80000000))
|
||||
direct->uppos = direct->pos;
|
||||
}
|
||||
direct->winsize = ntohs(dis->tcp->th_win);
|
||||
direct->winsize_calc = direct->winsize;
|
||||
if (direct->scale != SCALE_NONE) direct->winsize_calc <<= direct->scale;
|
||||
if (mss && !direct->mss) direct->mss = mss;
|
||||
if (scale != SCALE_NONE) direct->scale = scale;
|
||||
|
||||
if (!direct->rseq_over_2G && ((direct->seq_last - direct->seq0) & 0x80000000))
|
||||
direct->rseq_over_2G = true;
|
||||
if (!reverse->rseq_over_2G && ((reverse->seq_last - reverse->seq0) & 0x80000000))
|
||||
reverse->rseq_over_2G = true;
|
||||
}
|
||||
|
||||
static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct dissect *dis)
|
||||
{
|
||||
uint8_t scale;
|
||||
uint16_t mss;
|
||||
|
||||
if (bReverse)
|
||||
{
|
||||
t->pcounter_reply++;
|
||||
t->pdcounter_reply += !!len_payload;
|
||||
t->pbcounter_reply += len_payload;
|
||||
t->pos.server.pcounter++;
|
||||
t->pos.server.pdcounter += !!dis->len_payload;
|
||||
t->pos.server.pbcounter += dis->len_payload;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
t->pcounter_orig++;
|
||||
t->pdcounter_orig += !!len_payload;
|
||||
t->pbcounter_orig += len_payload;
|
||||
t->pos.client.pcounter++;
|
||||
t->pos.client.pdcounter += !!dis->len_payload;
|
||||
t->pos.client.pbcounter += dis->len_payload;
|
||||
}
|
||||
|
||||
if (tcphdr)
|
||||
if (dis->tcp)
|
||||
{
|
||||
if (tcp_syn_segment(tcphdr))
|
||||
if (tcp_syn_segment(dis->tcp))
|
||||
{
|
||||
if (t->state != SYN) ConntrackReInitTrack(t); // erase current entry
|
||||
t->seq0 = ntohl(tcphdr->th_seq);
|
||||
if (t->pos.state != SYN) ConntrackReInitTrack(t); // erase current entry
|
||||
t->pos.client.seq0 = ntohl(dis->tcp->th_seq);
|
||||
}
|
||||
else if (tcp_synack_segment(tcphdr))
|
||||
else if (tcp_synack_segment(dis->tcp))
|
||||
{
|
||||
// ignore SA dups
|
||||
uint32_t seq0 = ntohl(tcphdr->th_ack) - 1;
|
||||
if (t->state != SYN && t->seq0 != seq0)
|
||||
uint32_t seq0 = ntohl(dis->tcp->th_ack) - 1;
|
||||
if (t->pos.state != SYN && t->pos.client.seq0 != seq0)
|
||||
ConntrackReInitTrack(t); // erase current entry
|
||||
if (!t->seq0) t->seq0 = seq0;
|
||||
t->ack0 = ntohl(tcphdr->th_seq);
|
||||
if (!t->pos.client.seq0) t->pos.client.seq0 = seq0;
|
||||
t->pos.server.seq0 = ntohl(dis->tcp->th_seq);
|
||||
}
|
||||
else if (tcphdr->th_flags & (TH_FIN | TH_RST))
|
||||
else if (dis->tcp->th_flags & (TH_FIN | TH_RST))
|
||||
{
|
||||
t->state = FIN;
|
||||
t->pos.state = FIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t->state == SYN)
|
||||
if (t->pos.state == SYN)
|
||||
{
|
||||
t->state = ESTABLISHED;
|
||||
if (!bReverse && !t->ack0) t->ack0 = ntohl(tcphdr->th_ack) - 1;
|
||||
t->pos.state = ESTABLISHED;
|
||||
if (!bReverse && !t->pos.server.seq0) t->pos.server.seq0 = ntohl(dis->tcp->th_ack) - 1;
|
||||
}
|
||||
}
|
||||
scale = tcp_find_scale_factor(tcphdr);
|
||||
mss = ntohs(tcp_find_mss(tcphdr));
|
||||
if (bReverse)
|
||||
{
|
||||
t->pos_orig = t->seq_last = ntohl(tcphdr->th_ack);
|
||||
t->ack_last = ntohl(tcphdr->th_seq);
|
||||
t->pos_reply = t->ack_last + len_payload;
|
||||
t->winsize_reply = ntohs(tcphdr->th_win);
|
||||
t->winsize_reply_calc = t->winsize_reply;
|
||||
if (t->scale_reply != SCALE_NONE) t->winsize_reply_calc <<= t->scale_reply;
|
||||
if (mss && !t->mss_reply) t->mss_reply = mss;
|
||||
if (scale != SCALE_NONE) t->scale_reply = scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
t->seq_last = ntohl(tcphdr->th_seq);
|
||||
t->pos_orig = t->seq_last + len_payload;
|
||||
t->pos_reply = t->ack_last = ntohl(tcphdr->th_ack);
|
||||
t->winsize_orig = ntohs(tcphdr->th_win);
|
||||
t->winsize_orig_calc = t->winsize_orig;
|
||||
if (t->scale_orig != SCALE_NONE) t->winsize_orig_calc <<= t->scale_orig;
|
||||
if (mss && !t->mss_reply) t->mss_orig = mss;
|
||||
if (scale != SCALE_NONE) t->scale_orig = scale;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bReverse)
|
||||
{
|
||||
t->ack_last = t->pos_reply;
|
||||
t->pos_reply += len_payload;
|
||||
}
|
||||
else
|
||||
{
|
||||
t->seq_last = t->pos_orig;
|
||||
t->pos_orig += len_payload;
|
||||
}
|
||||
|
||||
ConntrackApplyPos(t, bReverse, dis);
|
||||
}
|
||||
|
||||
time(&t->t_last);
|
||||
clock_gettime(CLOCK_REALTIME, &t->pos.t_last);
|
||||
// make sure t_start gets exactly the same value as first t_last
|
||||
if (!t->t_start.tv_sec) t->t_start = t->pos.t_last;
|
||||
}
|
||||
|
||||
static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse)
|
||||
static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse)
|
||||
{
|
||||
t_conn conn, connswp;
|
||||
t_conntrack_pool *ctr;
|
||||
|
||||
ConntrackExtractConn(&conn, false, ip, ip6, tcphdr, udphdr);
|
||||
ConntrackExtractConn(&conn, false, dis);
|
||||
if ((ctr = ConntrackPoolSearch(*pp, &conn)))
|
||||
{
|
||||
if (bReverse) *bReverse = false;
|
||||
@@ -242,22 +244,22 @@ static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct ip
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse)
|
||||
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse)
|
||||
{
|
||||
return ConntrackPoolDoubleSearchPool(&p->pool, ip, ip6, tcphdr, udphdr, ctrack, bReverse);
|
||||
return ConntrackPoolDoubleSearchPool(&p->pool, dis, ctrack, bReverse);
|
||||
}
|
||||
|
||||
static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse)
|
||||
static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse)
|
||||
{
|
||||
t_conn conn, connswp;
|
||||
t_conntrack_pool *ctr;
|
||||
bool b_rev;
|
||||
uint8_t proto = tcphdr ? IPPROTO_TCP : udphdr ? IPPROTO_UDP : IPPROTO_NONE;
|
||||
uint8_t proto = dis->tcp ? IPPROTO_TCP : dis->udp ? IPPROTO_UDP : IPPROTO_NONE;
|
||||
|
||||
ConntrackExtractConn(&conn, false, ip, ip6, tcphdr, udphdr);
|
||||
ConntrackExtractConn(&conn, false, dis);
|
||||
if ((ctr = ConntrackPoolSearch(*pp, &conn)))
|
||||
{
|
||||
ConntrackFeedPacket(&ctr->track, (b_rev = false), tcphdr, len_payload);
|
||||
ConntrackFeedPacket(&ctr->track, (b_rev = false), dis);
|
||||
goto ok;
|
||||
}
|
||||
else
|
||||
@@ -265,16 +267,16 @@ static bool ConntrackPoolFeedPool(t_conntrack_pool **pp, const struct ip *ip, co
|
||||
connswap(&conn, &connswp);
|
||||
if ((ctr = ConntrackPoolSearch(*pp, &connswp)))
|
||||
{
|
||||
ConntrackFeedPacket(&ctr->track, (b_rev = true), tcphdr, len_payload);
|
||||
ConntrackFeedPacket(&ctr->track, (b_rev = true), dis);
|
||||
goto ok;
|
||||
}
|
||||
}
|
||||
b_rev = tcphdr && tcp_synack_segment(tcphdr);
|
||||
if ((tcphdr && tcp_syn_segment(tcphdr)) || b_rev || udphdr)
|
||||
b_rev = dis->tcp && tcp_synack_segment(dis->tcp);
|
||||
if ((dis->tcp && tcp_syn_segment(dis->tcp)) || b_rev || dis->udp)
|
||||
{
|
||||
if ((ctr = ConntrackNew(pp, b_rev ? &connswp : &conn)))
|
||||
{
|
||||
ConntrackFeedPacket(&ctr->track, b_rev, tcphdr, len_payload);
|
||||
ConntrackFeedPacket(&ctr->track, b_rev, dis);
|
||||
goto ok;
|
||||
}
|
||||
}
|
||||
@@ -285,16 +287,16 @@ ok:
|
||||
if (bReverse) *bReverse = b_rev;
|
||||
return true;
|
||||
}
|
||||
bool ConntrackPoolFeed(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse)
|
||||
bool ConntrackPoolFeed(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse)
|
||||
{
|
||||
return ConntrackPoolFeedPool(&p->pool, ip, ip6, tcphdr, udphdr, len_payload, ctrack, bReverse);
|
||||
return ConntrackPoolFeedPool(&p->pool, dis, ctrack, bReverse);
|
||||
}
|
||||
|
||||
static bool ConntrackPoolDropPool(t_conntrack_pool **pp, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr)
|
||||
static bool ConntrackPoolDropPool(t_conntrack_pool **pp, const struct dissect *dis)
|
||||
{
|
||||
t_conn conn, connswp;
|
||||
t_conntrack_pool *t;
|
||||
ConntrackExtractConn(&conn, false, ip, ip6, tcphdr, udphdr);
|
||||
ConntrackExtractConn(&conn, false, dis);
|
||||
if (!(t = ConntrackPoolSearch(*pp, &conn)))
|
||||
{
|
||||
connswap(&conn, &connswp);
|
||||
@@ -304,32 +306,34 @@ static bool ConntrackPoolDropPool(t_conntrack_pool **pp, const struct ip *ip, co
|
||||
HASH_DEL(*pp, t); ConntrackFreeElem(t);
|
||||
return true;
|
||||
}
|
||||
bool ConntrackPoolDrop(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr)
|
||||
bool ConntrackPoolDrop(t_conntrack *p, const struct dissect *dis)
|
||||
{
|
||||
return ConntrackPoolDropPool(&p->pool, ip, ip6, tcphdr, udphdr);
|
||||
return ConntrackPoolDropPool(&p->pool, dis);
|
||||
}
|
||||
|
||||
void ConntrackPoolPurge(t_conntrack *p)
|
||||
{
|
||||
time_t tidle, tnow = time(NULL);
|
||||
time_t tidle;
|
||||
struct timespec tnow;
|
||||
t_conntrack_pool *t, *tmp;
|
||||
|
||||
if ((tnow - p->t_last_purge) >= p->t_purge_interval)
|
||||
if (clock_gettime(CLOCK_REALTIME, &tnow)) return;
|
||||
if ((tnow.tv_sec - p->t_last_purge) >= p->t_purge_interval)
|
||||
{
|
||||
HASH_ITER(hh, p->pool, t, tmp) {
|
||||
tidle = tnow - t->track.t_last;
|
||||
tidle = tnow.tv_sec - t->track.pos.t_last.tv_sec;
|
||||
if (t->track.b_cutoff ||
|
||||
(t->conn.l4proto == IPPROTO_TCP && (
|
||||
(t->track.state == SYN && tidle >= p->timeout_syn) ||
|
||||
(t->track.state == ESTABLISHED && tidle >= p->timeout_established) ||
|
||||
(t->track.state == FIN && tidle >= p->timeout_fin))
|
||||
(t->track.pos.state == SYN && tidle >= p->timeout_syn) ||
|
||||
(t->track.pos.state == ESTABLISHED && tidle >= p->timeout_established) ||
|
||||
(t->track.pos.state == FIN && tidle >= p->timeout_fin))
|
||||
) || (t->conn.l4proto == IPPROTO_UDP && tidle >= p->timeout_udp)
|
||||
)
|
||||
{
|
||||
HASH_DEL(p->pool, t); ConntrackFreeElem(t);
|
||||
}
|
||||
}
|
||||
p->t_last_purge = tnow;
|
||||
p->t_last_purge = tnow.tv_sec;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,29 +345,31 @@ static void taddr2str(uint8_t l3proto, const t_addr *a, char *buf, size_t bufsiz
|
||||
void ConntrackPoolDump(const t_conntrack *p)
|
||||
{
|
||||
t_conntrack_pool *t, *tmp;
|
||||
struct timespec tnow;
|
||||
char sa1[40], sa2[40];
|
||||
time_t tnow = time(NULL);
|
||||
|
||||
if (clock_gettime(CLOCK_REALTIME, &tnow)) return;
|
||||
HASH_ITER(hh, p->pool, t, tmp) {
|
||||
taddr2str(t->conn.l3proto, &t->conn.src, sa1, sizeof(sa1));
|
||||
taddr2str(t->conn.l3proto, &t->conn.dst, sa2, sizeof(sa2));
|
||||
printf("%s [%s]:%u => [%s]:%u : %s : t0=%llu last=t0+%llu now=last+%llu orig=d%llu/n%llu/b%llu reply=d%llu/n%llu/b%lld ",
|
||||
printf("%s [%s]:%u => [%s]:%u : %s : t0=%llu last=t0+%llu now=last+%llu client=d%llu/n%llu/b%llu server=d%llu/n%llu/b%lld ",
|
||||
proto_name(t->conn.l4proto),
|
||||
sa1, t->conn.sport, sa2, t->conn.dport,
|
||||
t->conn.l4proto == IPPROTO_TCP ? connstate_s[t->track.state] : "-",
|
||||
(unsigned long long)t->track.t_start, (unsigned long long)(t->track.t_last - t->track.t_start), (unsigned long long)(tnow - t->track.t_last),
|
||||
(unsigned long long)t->track.pdcounter_orig, (unsigned long long)t->track.pcounter_orig, (unsigned long long)t->track.pbcounter_orig,
|
||||
(unsigned long long)t->track.pdcounter_reply, (unsigned long long)t->track.pcounter_reply, (unsigned long long)t->track.pbcounter_reply);
|
||||
t->conn.l4proto == IPPROTO_TCP ? connstate_s[t->track.pos.state] : "-",
|
||||
(unsigned long long)t->track.t_start.tv_sec, (unsigned long long)(t->track.pos.t_last.tv_sec - t->track.t_start.tv_sec), (unsigned long long)(tnow.tv_sec - t->track.pos.t_last.tv_sec),
|
||||
(unsigned long long)t->track.pos.client.pdcounter, (unsigned long long)t->track.pos.client.pcounter, (unsigned long long)t->track.pos.client.pbcounter,
|
||||
(unsigned long long)t->track.pos.server.pdcounter, (unsigned long long)t->track.pos.server.pcounter, (unsigned long long)t->track.pos.server.pbcounter);
|
||||
if (t->conn.l4proto == IPPROTO_TCP)
|
||||
printf("seq0=%u rseq=%u pos_orig=%u ack0=%u rack=%u pos_reply=%u mss_orig=%u mss_reply=%u wsize_orig=%u:%d wsize_reply=%u:%d",
|
||||
t->track.seq0, t->track.seq_last - t->track.seq0, t->track.pos_orig - t->track.seq0,
|
||||
t->track.ack0, t->track.ack_last - t->track.ack0, t->track.pos_reply - t->track.ack0,
|
||||
t->track.mss_orig, t->track.mss_reply,
|
||||
t->track.winsize_orig, t->track.scale_orig == SCALE_NONE ? -1 : t->track.scale_orig,
|
||||
t->track.winsize_reply, t->track.scale_reply == SCALE_NONE ? -1 : t->track.scale_reply);
|
||||
printf("seq0=%u rseq=%u client.pos=%u ack0=%u rack=%u server.pos=%u client.mss=%u server.mss=%u client.wsize=%u:%d server.wsize=%u:%d",
|
||||
t->track.pos.client.seq0, t->track.pos.client.seq_last - t->track.pos.client.seq0, t->track.pos.client.pos - t->track.pos.client.seq0,
|
||||
t->track.pos.server.seq0, t->track.pos.server.seq_last - t->track.pos.server.seq0, t->track.pos.server.pos - t->track.pos.server.seq0,
|
||||
t->track.pos.client.mss, t->track.pos.server.mss,
|
||||
t->track.pos.client.winsize, t->track.pos.client.scale == SCALE_NONE ? -1 : t->track.pos.client.scale,
|
||||
t->track.pos.server.winsize, t->track.pos.server.scale == SCALE_NONE ? -1 : t->track.pos.server.scale);
|
||||
else
|
||||
printf("rseq=%u pos_orig=%u rack=%u pos_reply=%u",
|
||||
t->track.seq_last, t->track.pos_orig,
|
||||
t->track.ack_last, t->track.pos_reply);
|
||||
printf("rseq=%u client.pos=%u rack=%u server.pos=%u",
|
||||
t->track.pos.client.seq_last, t->track.pos.client.pos,
|
||||
t->track.pos.server.seq_last, t->track.pos.server.pos);
|
||||
printf(" req_retrans=%u cutoff=%u lua_in_cutoff=%u lua_out_cutoff=%u hostname=%s l7proto=%s\n",
|
||||
t->track.req_retrans_counter, t->track.b_cutoff, t->track.b_lua_in_cutoff, t->track.b_lua_out_cutoff, t->track.hostname, l7proto_str(t->track.l7proto));
|
||||
};
|
||||
@@ -394,17 +400,30 @@ bool ReasmResize(t_reassemble *reasm, size_t new_size)
|
||||
if (reasm->size_present > new_size) reasm->size_present = new_size;
|
||||
return true;
|
||||
}
|
||||
#define REASM_MAX_NEG 0x100000
|
||||
bool ReasmFeed(t_reassemble *reasm, uint32_t seq, const void *payload, size_t len)
|
||||
{
|
||||
if (reasm->seq != seq) return false; // fail session if out of sequence
|
||||
|
||||
size_t szcopy;
|
||||
szcopy = reasm->size - reasm->size_present;
|
||||
if (len < szcopy) szcopy = len;
|
||||
memcpy(reasm->packet + reasm->size_present, payload, szcopy);
|
||||
reasm->size_present += szcopy;
|
||||
reasm->seq += (uint32_t)szcopy;
|
||||
uint32_t dseq = seq - reasm->seq;
|
||||
if (dseq && (dseq < REASM_MAX_NEG))
|
||||
return false; // fail session if a gap about to appear
|
||||
uint32_t neg_overlap = reasm->seq - seq;
|
||||
if (neg_overlap > REASM_MAX_NEG)
|
||||
return false; // too big minus
|
||||
|
||||
size_t szcopy, szignore;
|
||||
szignore = (neg_overlap > reasm->size_present) ? neg_overlap - reasm->size_present : 0;
|
||||
if (szignore>=len) return true; // everyting is before the starting pos
|
||||
szcopy = len - szignore;
|
||||
neg_overlap -= szignore;
|
||||
if ((reasm->size_present - neg_overlap + szcopy) > reasm->size)
|
||||
return false; // buffer overflow
|
||||
// in case of seq overlap new data replaces old - unix behavior
|
||||
memcpy(reasm->packet + reasm->size_present - neg_overlap, payload + szignore, szcopy);
|
||||
if (szcopy>neg_overlap)
|
||||
{
|
||||
reasm->size_present += szcopy - neg_overlap;
|
||||
reasm->seq += (uint32_t)szcopy - neg_overlap;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool ReasmHasSpace(t_reassemble *reasm, size_t len)
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <stdint.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#define __FAVOR_BSD
|
||||
@@ -17,8 +16,10 @@
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#include "conntrack_base.h"
|
||||
#include "packet_queue.h"
|
||||
#include "protocol.h"
|
||||
#include "darkmagic.h"
|
||||
|
||||
//#define HASH_BLOOM 20
|
||||
#define HASH_NONFATAL_OOM 1
|
||||
@@ -43,43 +44,27 @@ typedef struct
|
||||
// this structure helps to reassemble continuous packets streams. it does not support out-of-orders
|
||||
typedef struct {
|
||||
uint8_t *packet; // allocated for size during reassemble request. requestor must know the message size.
|
||||
uint32_t seq; // current seq number. if a packet comes with an unexpected seq - it fails reassemble session.
|
||||
uint32_t seq; // current seq number. if a packet comes with unsupported seq overlap - it fails reassemble session.
|
||||
size_t size; // expected message size. success means that we have received exactly 'size' bytes and have them in 'packet'
|
||||
size_t size_present; // how many bytes already stored in 'packet'
|
||||
} t_reassemble;
|
||||
|
||||
// SYN - SYN or SYN/ACK received
|
||||
// ESTABLISHED - any except SYN or SYN/ACK received
|
||||
// FIN - FIN or RST received
|
||||
typedef enum {SYN=0, ESTABLISHED, FIN} t_connstate;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool bCheckDone, bCheckResult, bCheckExcluded; // hostlist check result cache
|
||||
uint8_t ipproto;
|
||||
|
||||
struct timespec t_start;
|
||||
|
||||
// this block of data can change between delayed (queued) packets. need to remeber this data for each packet for further replay
|
||||
t_ctrack_positions pos;
|
||||
|
||||
struct desync_profile *dp; // desync profile cache
|
||||
bool dp_search_complete;
|
||||
|
||||
// common state
|
||||
time_t t_start, t_last;
|
||||
uint64_t pcounter_orig, pcounter_reply; // packet counter
|
||||
uint64_t pdcounter_orig, pdcounter_reply; // data packet counter (with payload)
|
||||
uint64_t pbcounter_orig, pbcounter_reply; // transferred byte counter. includes retransmissions. it's not the same as relative seq.
|
||||
uint32_t pos_orig, pos_reply; // TCP: seq_last+payload, ack_last+payload UDP: sum of all seen payload lenghts including current
|
||||
uint32_t seq_last, ack_last; // TCP: last seen seq and ack UDP: sum of all seen payload lenghts NOT including current
|
||||
|
||||
// tcp only state, not used in udp
|
||||
t_connstate state;
|
||||
uint32_t seq0, ack0; // starting seq and ack
|
||||
uint16_t winsize_orig, winsize_reply; // last seen window size
|
||||
uint8_t scale_orig, scale_reply; // last seen window scale factor. SCALE_NONE if none
|
||||
uint32_t winsize_orig_calc, winsize_reply_calc; // calculated window size
|
||||
uint16_t mss_orig, mss_reply;
|
||||
|
||||
uint8_t req_retrans_counter; // number of request retransmissions
|
||||
bool req_seq_present,req_seq_finalized,req_seq_abandoned;
|
||||
uint32_t req_seq_start,req_seq_end; // sequence interval of the request (to track retransmissions)
|
||||
bool failure_detect_finalized;
|
||||
|
||||
uint8_t incoming_ttl;
|
||||
|
||||
@@ -96,7 +81,7 @@ typedef struct
|
||||
int lua_state; // registry index of associated LUA object
|
||||
int lua_instance_cutoff; // registry index of per connection function instance cutoff table
|
||||
|
||||
t_reassemble reasm_orig;
|
||||
t_reassemble reasm_client;
|
||||
struct rawpacket_tailhead delayed;
|
||||
} t_ctrack;
|
||||
|
||||
@@ -116,11 +101,11 @@ typedef struct
|
||||
|
||||
void ConntrackPoolInit(t_conntrack *p, time_t purge_interval, uint32_t timeout_syn, uint32_t timeout_established, uint32_t timeout_fin, uint32_t timeout_udp);
|
||||
void ConntrackPoolDestroy(t_conntrack *p);
|
||||
bool ConntrackPoolFeed(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, size_t len_payload, t_ctrack **ctrack, bool *bReverse);
|
||||
bool ConntrackPoolFeed(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse);
|
||||
// do not create, do not update. only find existing
|
||||
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse);
|
||||
bool ConntrackPoolDrop(t_conntrack *p, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr);
|
||||
void CaonntrackExtractConn(t_conn *c, bool bReverse, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr);
|
||||
bool ConntrackPoolDoubleSearch(t_conntrack *p, const struct dissect *dis, t_ctrack **ctrack, bool *bReverse);
|
||||
bool ConntrackPoolDrop(t_conntrack *p, const struct dissect *dis);
|
||||
void ConntrackExtractConn(t_conn *c, bool bReverse, const struct dissect *dis);
|
||||
void ConntrackPoolDump(const t_conntrack *p);
|
||||
void ConntrackPoolPurge(t_conntrack *p);
|
||||
void ConntrackClearHostname(t_ctrack *track);
|
||||
|
||||
42
nfq2/conntrack_base.h
Normal file
42
nfq2/conntrack_base.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
#define CTRACK_T_SYN 60
|
||||
#define CTRACK_T_FIN 60
|
||||
#define CTRACK_T_EST 300
|
||||
#define CTRACK_T_UDP 60
|
||||
|
||||
// SYN - SYN or SYN/ACK received
|
||||
// ESTABLISHED - any except SYN or SYN/ACK received
|
||||
// FIN - FIN or RST received
|
||||
typedef enum {SYN=0, ESTABLISHED, FIN} t_connstate;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t pcounter; // packet counter
|
||||
uint64_t pdcounter; // data packet counter (with payload)
|
||||
uint64_t pbcounter; // transferred byte counter. includes retransmissions. it's not the same as relative seq.
|
||||
uint32_t ip6flow;
|
||||
|
||||
// tcp only state, not used in udp
|
||||
uint32_t pos; // TCP: seq_last+payload, ack_last+payload UDP: sum of all seen payload lenghts including current
|
||||
uint32_t uppos; // max seen position. useful to detect retransmissions
|
||||
uint32_t uppos_prev; // previous max seen position. useful to detect retransmissions
|
||||
uint32_t seq_last; // TCP: last seen seq and ack UDP: sum of all seen payload lenghts NOT including current
|
||||
uint32_t seq0; // starting seq and ack
|
||||
uint16_t winsize; // last seen window size
|
||||
uint16_t mss;
|
||||
uint32_t winsize_calc; // calculated window size
|
||||
uint8_t scale; // last seen window scale factor. SCALE_NONE if none
|
||||
bool rseq_over_2G;
|
||||
} t_ctrack_position;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct timespec t_last;
|
||||
t_connstate state;
|
||||
t_ctrack_position client, server;
|
||||
}
|
||||
t_ctrack_positions;
|
||||
233
nfq2/darkmagic.c
233
nfq2/darkmagic.c
@@ -40,9 +40,6 @@
|
||||
#include <linux/genetlink.h>
|
||||
#include <libmnl/libmnl.h>
|
||||
#include <net/if.h>
|
||||
#define _LINUX_IF_H // prevent conflict between linux/if.h and net/if.h in old gcc 4.x
|
||||
#include <linux/wireless.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
uint32_t net32_add(uint32_t netorder_value, uint32_t cpuorder_increment)
|
||||
@@ -550,6 +547,33 @@ void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis)
|
||||
}
|
||||
}
|
||||
|
||||
void reverse_ip(struct ip *ip, struct ip6_hdr *ip6)
|
||||
{
|
||||
if (ip)
|
||||
{
|
||||
struct in_addr temp = ip->ip_src;
|
||||
ip->ip_src = ip->ip_dst;
|
||||
ip->ip_dst = temp;
|
||||
ip4_fix_checksum(ip);
|
||||
}
|
||||
if (ip6)
|
||||
{
|
||||
struct in6_addr temp = ip6->ip6_src;
|
||||
ip6->ip6_src = ip6->ip6_dst;
|
||||
ip6->ip6_dst = temp;
|
||||
}
|
||||
}
|
||||
void reverse_tcp(struct tcphdr *tcp)
|
||||
{
|
||||
uint16_t tport = tcp->th_sport;
|
||||
tcp->th_sport = tcp->th_dport;
|
||||
tcp->th_dport = tport;
|
||||
|
||||
uint32_t tseq = tcp->th_seq;
|
||||
tcp->th_seq = tcp->th_ack;
|
||||
tcp->th_ack = tseq;
|
||||
}
|
||||
|
||||
|
||||
uint8_t ttl46(const struct ip *ip, const struct ip6_hdr *ip6)
|
||||
{
|
||||
@@ -721,13 +745,36 @@ bool prepare_low_appdata()
|
||||
return b;
|
||||
}
|
||||
|
||||
BOOL JobSandbox()
|
||||
{
|
||||
BOOL bRes = FALSE;
|
||||
HANDLE hJob;
|
||||
JOBOBJECT_BASIC_LIMIT_INFORMATION basic_limit;
|
||||
JOBOBJECT_BASIC_UI_RESTRICTIONS basic_ui;
|
||||
|
||||
if (hJob = CreateJobObjectW(NULL, NULL))
|
||||
{
|
||||
basic_limit.LimitFlags = JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
|
||||
// prevent child process creation
|
||||
basic_limit.ActiveProcessLimit = 1;
|
||||
// prevent some UI interaction and settings change
|
||||
basic_ui.UIRestrictionsClass = JOB_OBJECT_UILIMIT_DESKTOP | JOB_OBJECT_UILIMIT_DISPLAYSETTINGS | JOB_OBJECT_UILIMIT_EXITWINDOWS | JOB_OBJECT_UILIMIT_GLOBALATOMS | JOB_OBJECT_UILIMIT_HANDLES | JOB_OBJECT_UILIMIT_READCLIPBOARD | JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS | JOB_OBJECT_UILIMIT_WRITECLIPBOARD;
|
||||
bRes = SetInformationJobObject(hJob, JobObjectBasicLimitInformation, &basic_limit, sizeof(basic_limit)) &&
|
||||
SetInformationJobObject(hJob, JobObjectBasicUIRestrictions, &basic_ui, sizeof(basic_ui)) &&
|
||||
AssignProcessToJobObject(hJob, GetCurrentProcess());
|
||||
w_win32_error = GetLastError();
|
||||
CloseHandle(hJob);
|
||||
}
|
||||
return bRes;
|
||||
}
|
||||
|
||||
|
||||
#define WINDIVERT_DEVICE_NAME "WinDivert"
|
||||
static bool b_isandbox_set = false;
|
||||
static bool b_sandbox_set = false;
|
||||
bool win_sandbox(void)
|
||||
{
|
||||
// there's no way to return privs
|
||||
if (!b_isandbox_set)
|
||||
if (!b_sandbox_set)
|
||||
{
|
||||
if (!RemoveTokenPrivs())
|
||||
return FALSE;
|
||||
@@ -737,8 +784,9 @@ bool win_sandbox(void)
|
||||
return FALSE;
|
||||
if (!LowMandatoryLevel())
|
||||
return false;
|
||||
// for LUA code to find where to store files
|
||||
b_isandbox_set = true;
|
||||
if (!JobSandbox())
|
||||
return false;
|
||||
b_sandbox_set = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1256,14 +1304,21 @@ bool rawsend(const struct sockaddr* dst,uint32_t fwmark,const char *ifout,const
|
||||
{
|
||||
WINDIVERT_ADDRESS wa;
|
||||
|
||||
if (!ifout) return false;
|
||||
|
||||
memset(&wa,0,sizeof(wa));
|
||||
// pseudo interface id IfIdx.SubIfIdx
|
||||
if (sscanf(ifout,"%u.%u",&wa.Network.IfIdx,&wa.Network.SubIfIdx)!=2)
|
||||
if (ifout && *ifout)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
if (sscanf(ifout,"%u.%u",&wa.Network.IfIdx,&wa.Network.SubIfIdx)!=2)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 1 - typically loopback
|
||||
wa.Network.IfIdx=1;
|
||||
wa.Network.SubIfIdx=0;
|
||||
}
|
||||
wa.Outbound=1;
|
||||
wa.IPChecksum=1;
|
||||
@@ -1578,9 +1633,9 @@ bool rawsend_queue(struct rawpacket_tailhead *q)
|
||||
|
||||
// linux-specific wlan retrieval implementation
|
||||
|
||||
typedef void netlink_prepare_nlh_cb_t(struct nlmsghdr *nlh);
|
||||
typedef void netlink_prepare_nlh_cb_t(struct nlmsghdr *nlh, void *param);
|
||||
|
||||
static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, uint16_t flags, uint8_t cmd, uint8_t version, netlink_prepare_nlh_cb_t cb_prepare_nlh, mnl_cb_t cb_data, void *data)
|
||||
static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, uint16_t flags, uint8_t cmd, uint8_t version, netlink_prepare_nlh_cb_t cb_prepare_nlh, void *prepare_data, mnl_cb_t cb_data, void *data)
|
||||
{
|
||||
char buf[MNL_SOCKET_BUFFER_SIZE];
|
||||
struct nlmsghdr *nlh;
|
||||
@@ -1595,7 +1650,7 @@ static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, u
|
||||
genl->cmd = cmd;
|
||||
genl->version = version;
|
||||
|
||||
if (cb_prepare_nlh) cb_prepare_nlh(nlh);
|
||||
if (cb_prepare_nlh) cb_prepare_nlh(nlh, prepare_data);
|
||||
|
||||
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
|
||||
{
|
||||
@@ -1619,7 +1674,7 @@ static bool netlink_genl_simple_transact(struct mnl_socket* nl, uint16_t type, u
|
||||
return false;
|
||||
}
|
||||
|
||||
static void wlan_id_prepare(struct nlmsghdr *nlh)
|
||||
static void wlan_id_prepare(struct nlmsghdr *nlh, void *param)
|
||||
{
|
||||
mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, "nl80211");
|
||||
}
|
||||
@@ -1651,7 +1706,7 @@ static int wlan_id_cb(const struct nlmsghdr *nlh, void *data)
|
||||
static uint16_t wlan_get_family_id(struct mnl_socket* nl)
|
||||
{
|
||||
uint16_t id;
|
||||
return netlink_genl_simple_transact(nl, GENL_ID_CTRL, NLM_F_REQUEST | NLM_F_ACK, CTRL_CMD_GETFAMILY, 1, wlan_id_prepare, wlan_id_cb, &id) ? id : 0;
|
||||
return netlink_genl_simple_transact(nl, GENL_ID_CTRL, NLM_F_REQUEST | NLM_F_ACK, CTRL_CMD_GETFAMILY, 1, wlan_id_prepare, NULL, wlan_id_cb, &id) ? id : 0;
|
||||
}
|
||||
|
||||
static int wlan_info_attr_cb(const struct nlattr *attr, void *data)
|
||||
@@ -1686,42 +1741,130 @@ static int wlan_info_attr_cb(const struct nlattr *attr, void *data)
|
||||
}
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
struct wlan_info_req
|
||||
{
|
||||
struct wlan_interface_collection *wc;
|
||||
bool bReqSSID;
|
||||
};
|
||||
static int wlan_info_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
int ret;
|
||||
struct wlan_info_req *wr = (struct wlan_info_req*)data;
|
||||
if (wr->wc->count>=WLAN_INTERFACE_MAX) return MNL_CB_OK;
|
||||
memset(wr->wc->wlan + wr->wc->count,0,sizeof(struct wlan_interface));
|
||||
ret = mnl_attr_parse(nlh, sizeof(struct genlmsghdr), wlan_info_attr_cb, wr->wc->wlan + wr->wc->count);
|
||||
if (ret>=0 && (!wr->bReqSSID || *wr->wc->wlan[wr->wc->count].ssid) && *wr->wc->wlan[wr->wc->count].ifname && wr->wc->wlan[wr->wc->count].ifindex)
|
||||
wr->wc->count++;
|
||||
return ret;
|
||||
}
|
||||
static bool wlan_info(struct mnl_socket* nl, uint16_t wlan_family_id, struct wlan_interface_collection* w, bool bReqSSID)
|
||||
{
|
||||
struct wlan_info_req req = { .bReqSSID = bReqSSID, .wc = w };
|
||||
return netlink_genl_simple_transact(nl, wlan_family_id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP, NL80211_CMD_GET_INTERFACE, 0, NULL, NULL, wlan_info_cb, &req);
|
||||
}
|
||||
|
||||
|
||||
static void scan_prepare(struct nlmsghdr *nlh, void *param)
|
||||
{
|
||||
mnl_attr_put_u32(nlh, NL80211_ATTR_IFINDEX, *(int*)param);
|
||||
}
|
||||
static uint8_t *find_ie(uint8_t *buf, size_t len, uint8_t ie)
|
||||
{
|
||||
while (len>=2)
|
||||
{
|
||||
if (len<(2+buf[1])) break;
|
||||
if (buf[0]==ie) return buf;
|
||||
buf+=buf[1]+2;
|
||||
len-=buf[1]+2;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
static int scan_info_attr_cb(const struct nlattr *attr, void *data)
|
||||
{
|
||||
struct wlan_interface *wlan = (struct wlan_interface *)data;
|
||||
const struct nlattr *nested;
|
||||
uint8_t *payload, *ie;
|
||||
uint16_t payload_len;
|
||||
bool ok;
|
||||
|
||||
switch(mnl_attr_get_type(attr))
|
||||
{
|
||||
case NL80211_ATTR_IFINDEX:
|
||||
if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
|
||||
{
|
||||
DLOG_PERROR("mnl_attr_validate");
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
wlan->ifindex = mnl_attr_get_u32(attr);
|
||||
if (!if_indextoname(wlan->ifindex, wlan->ifname))
|
||||
DLOG_PERROR("if_indextoname");
|
||||
break;
|
||||
case NL80211_ATTR_BSS:
|
||||
if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
|
||||
{
|
||||
DLOG_PERROR("mnl_attr_validate");
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
ok = false;
|
||||
mnl_attr_for_each_nested(nested, attr)
|
||||
{
|
||||
if (mnl_attr_get_type(nested)==NL80211_BSS_STATUS)
|
||||
{
|
||||
uint32_t status = mnl_attr_get_u32(nested);
|
||||
if (status==NL80211_BSS_STATUS_ASSOCIATED || status==NL80211_BSS_STATUS_AUTHENTICATED || status==NL80211_BSS_STATUS_IBSS_JOINED)
|
||||
{
|
||||
ok=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ok) break;
|
||||
mnl_attr_for_each_nested(nested, attr)
|
||||
{
|
||||
switch(mnl_attr_get_type(nested))
|
||||
{
|
||||
case NL80211_BSS_INFORMATION_ELEMENTS:
|
||||
payload_len = mnl_attr_get_payload_len(nested);
|
||||
payload = mnl_attr_get_payload(nested);
|
||||
ie = find_ie(payload,payload_len,0);
|
||||
if (ie)
|
||||
{
|
||||
uint8_t l = ie[1];
|
||||
if (l>=(sizeof(wlan->ssid))) l=sizeof(wlan->ssid)-1;
|
||||
memcpy(wlan->ssid,ie+2,l);
|
||||
wlan->ssid[l]=0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
static int scan_info_cb(const struct nlmsghdr *nlh, void *data)
|
||||
{
|
||||
int ret;
|
||||
struct wlan_interface_collection *wc = (struct wlan_interface_collection*)data;
|
||||
if (wc->count>=WLAN_INTERFACE_MAX) return MNL_CB_OK;
|
||||
memset(wc->wlan+wc->count,0,sizeof(wc->wlan[0]));
|
||||
ret = mnl_attr_parse(nlh, sizeof(struct genlmsghdr), wlan_info_attr_cb, wc->wlan+wc->count);
|
||||
if (ret>=0 && *wc->wlan[wc->count].ifname && wc->wlan[wc->count].ifindex)
|
||||
{
|
||||
if (*wc->wlan[wc->count].ssid)
|
||||
wc->count++;
|
||||
else
|
||||
{
|
||||
// sometimes nl80211 does not return SSID but wireless ext does
|
||||
int wext_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (wext_fd!=-1)
|
||||
{
|
||||
struct iwreq req;
|
||||
snprintf(req.ifr_ifrn.ifrn_name,sizeof(req.ifr_ifrn.ifrn_name),"%s",wc->wlan[wc->count].ifname);
|
||||
req.u.essid.pointer = wc->wlan[wc->count].ssid;
|
||||
req.u.essid.length = sizeof(wc->wlan[wc->count].ssid);
|
||||
req.u.essid.flags = 0;
|
||||
if (ioctl(wext_fd, SIOCGIWESSID, &req)!=-1)
|
||||
if (*wc->wlan[wc->count].ssid)
|
||||
wc->count++;
|
||||
close(wext_fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = mnl_attr_parse(nlh, sizeof(struct genlmsghdr), scan_info_attr_cb, wc->wlan+wc->count);
|
||||
if (ret>=0 && *wc->wlan[wc->count].ssid && *wc->wlan[wc->count].ifname && wc->wlan[wc->count].ifindex)
|
||||
wc->count++;
|
||||
return ret;
|
||||
}
|
||||
static bool wlan_info(struct mnl_socket* nl, uint16_t wlan_family_id, struct wlan_interface_collection* w)
|
||||
static bool scan_info(struct mnl_socket* nl, uint16_t wlan_family_id, struct wlan_interface_collection* w)
|
||||
{
|
||||
return netlink_genl_simple_transact(nl, wlan_family_id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP, NL80211_CMD_GET_INTERFACE, 0, NULL, wlan_info_cb, w);
|
||||
struct wlan_interface_collection wc_all = { .count = 0 };
|
||||
// wlan_info does not return ssid since kernel 5.19
|
||||
// it's used to enumerate all wifi interfaces then call scan_info on each
|
||||
if (!wlan_info(nl, wlan_family_id, &wc_all, false)) return false;
|
||||
for(int i=0;i<wc_all.count;i++)
|
||||
if (!netlink_genl_simple_transact(nl, wlan_family_id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0, scan_prepare, (void*)&wc_all.wlan[i].ifindex, scan_info_cb, w))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool wlan_init80211(struct mnl_socket** nl)
|
||||
{
|
||||
if (!(*nl = mnl_socket_open(NETLINK_GENERIC)))
|
||||
@@ -1755,7 +1898,7 @@ static bool wlan_info_rate_limited(struct mnl_socket* nl, uint16_t wlan_family_i
|
||||
// do not purge too often to save resources
|
||||
if (wlan_info_last != now)
|
||||
{
|
||||
bres = wlan_info(nl,wlan_family_id,w);
|
||||
bres = scan_info(nl,wlan_family_id,w);
|
||||
wlan_info_last = now;
|
||||
}
|
||||
return bres;
|
||||
@@ -1781,10 +1924,6 @@ bool wlan_info_init(void)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool wlan_info_get(void)
|
||||
{
|
||||
return wlan_info(nl_wifi, id_nl80211, &wlans);
|
||||
}
|
||||
bool wlan_info_get_rate_limited(void)
|
||||
{
|
||||
return wlan_info_rate_limited(nl_wifi, id_nl80211, &wlans);
|
||||
|
||||
@@ -162,6 +162,8 @@ struct dissect
|
||||
size_t len_payload;
|
||||
};
|
||||
void proto_dissect_l3l4(const uint8_t *data, size_t len, struct dissect *dis);
|
||||
void reverse_ip(struct ip *ip, struct ip6_hdr *ip6);
|
||||
void reverse_tcp(struct tcphdr *tcp);
|
||||
|
||||
uint8_t ttl46(const struct ip *ip, const struct ip6_hdr *ip6);
|
||||
|
||||
@@ -190,7 +192,6 @@ extern struct wlan_interface_collection wlans;
|
||||
|
||||
void wlan_info_deinit(void);
|
||||
bool wlan_info_init(void);
|
||||
bool wlan_info_get(void);
|
||||
bool wlan_info_get_rate_limited(void);
|
||||
const char *wlan_ssid_search_ifname(const char *ifname);
|
||||
const char *wlan_ssid_search_ifidx(int ifidx);
|
||||
|
||||
925
nfq2/desync.c
925
nfq2/desync.c
File diff suppressed because it is too large
Load Diff
@@ -13,8 +13,10 @@
|
||||
|
||||
#ifdef __linux__
|
||||
#define DPI_DESYNC_FWMARK_DEFAULT 0x40000000
|
||||
#else
|
||||
#elif defined(SO_USER_COOKIE)
|
||||
#define DPI_DESYNC_FWMARK_DEFAULT 512
|
||||
#else
|
||||
#define DPI_DESYNC_FWMARK_DEFAULT 0
|
||||
#endif
|
||||
|
||||
uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifin, const char *ifout, const uint8_t *data_pkt, size_t len_pkt, uint8_t *mod_pkt, size_t *len_mod_pkt);
|
||||
|
||||
@@ -514,7 +514,7 @@ bool pf_is_empty(const port_filter *pf)
|
||||
|
||||
bool packet_pos_parse(const char *s, struct packet_pos *pos)
|
||||
{
|
||||
if (*s!='n' && *s!='d' && *s!='s' && *s!='b' && *s!='x' && *s!='a') return false;
|
||||
if (*s!='n' && *s!='d' && *s!='s' && *s!='p' && *s!='b' && *s!='x' && *s!='a') return false;
|
||||
pos->mode=*s;
|
||||
if (pos->mode=='x' || pos->mode=='a')
|
||||
{
|
||||
|
||||
@@ -258,7 +258,7 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
|
||||
// return : true = apply fooling, false = do not apply
|
||||
bool HostlistCheck(const struct desync_profile *dp, const char *host, bool no_match_subdomains, bool *excluded, bool bSkipReloadCheck)
|
||||
{
|
||||
DLOG("* hostlist check for profile %u\n",dp->n);
|
||||
DLOG("* hostlist check for profile %u (%s)\n",dp->n,PROFILE_NAME(dp));
|
||||
return HostlistCheck_(&dp->hl_collection, &dp->hl_collection_exclude, host, no_match_subdomains, excluded, bSkipReloadCheck);
|
||||
}
|
||||
|
||||
@@ -301,13 +301,34 @@ struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude,
|
||||
filename);
|
||||
}
|
||||
|
||||
static void HostlistsDebugProfile(const struct desync_profile *dp, const char *entity)
|
||||
{
|
||||
struct hostlist_item *hl_item;
|
||||
|
||||
LIST_FOREACH(hl_item, &dp->hl_collection, next)
|
||||
if (hl_item->hfile!=dp->hostlist_auto)
|
||||
{
|
||||
if (hl_item->hfile->filename)
|
||||
DLOG("%s %u (%s) include hostlist %s%s\n",entity, dp->n, PROFILE_NAME(dp), hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
else
|
||||
DLOG("%s %u (%s) include fixed hostlist%s\n",entity, dp->n, PROFILE_NAME(dp), hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
}
|
||||
LIST_FOREACH(hl_item, &dp->hl_collection_exclude, next)
|
||||
{
|
||||
if (hl_item->hfile->filename)
|
||||
DLOG("%s %u (%s) exclude hostlist %s%s\n",entity, dp->n,PROFILE_NAME(dp),hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
else
|
||||
DLOG("%s %u (%s) exclude fixed hostlist%s\n",entity, dp->n,PROFILE_NAME(dp),hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
}
|
||||
if (dp->hostlist_auto)
|
||||
DLOG("%s %u (%s) auto hostlist %s%s\n",entity, dp->n,PROFILE_NAME(dp),dp->hostlist_auto->filename,dp->hostlist_auto->hostlist ? "" : " (empty)");
|
||||
}
|
||||
void HostlistsDebug()
|
||||
{
|
||||
if (!params.debug) return;
|
||||
|
||||
struct hostlist_file *hfile;
|
||||
struct desync_profile_list *dpl;
|
||||
struct hostlist_item *hl_item;
|
||||
|
||||
LIST_FOREACH(hfile, ¶ms.hostlists, next)
|
||||
{
|
||||
@@ -319,22 +340,10 @@ void HostlistsDebug()
|
||||
|
||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
||||
{
|
||||
LIST_FOREACH(hl_item, &dpl->dp.hl_collection, next)
|
||||
if (hl_item->hfile!=dpl->dp.hostlist_auto)
|
||||
{
|
||||
if (hl_item->hfile->filename)
|
||||
DLOG("profile %u include hostlist %s%s\n",dpl->dp.n, hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
else
|
||||
DLOG("profile %u include fixed hostlist%s\n",dpl->dp.n, hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
}
|
||||
LIST_FOREACH(hl_item, &dpl->dp.hl_collection_exclude, next)
|
||||
{
|
||||
if (hl_item->hfile->filename)
|
||||
DLOG("profile %u exclude hostlist %s%s\n",dpl->dp.n,hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
else
|
||||
DLOG("profile %u exclude fixed hostlist%s\n",dpl->dp.n,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
}
|
||||
if (dpl->dp.hostlist_auto)
|
||||
DLOG("profile %u auto hostlist %s%s\n",dpl->dp.n,dpl->dp.hostlist_auto->filename,dpl->dp.hostlist_auto->hostlist ? "" : " (empty)");
|
||||
HostlistsDebugProfile(&dpl->dp, "profile");
|
||||
}
|
||||
LIST_FOREACH(dpl, ¶ms.desync_templates, next)
|
||||
{
|
||||
HostlistsDebugProfile(&dpl->dp, "template");
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user