515 Commits

Author SHA1 Message Date
juewuy
178228d8ec Merge branch 'master' into dev
# Conflicts:
#	ShellCrash.tar.gz
#	bin/version
#	version
2026-01-27 09:41:40 +08:00
juewuy
b9a29a69a7 ~1.9.4r1.1 pkg 2026-01-27 09:39:12 +08:00
juewuy
a0901b8083 ~优化 2026-01-27 09:38:41 +08:00
juewuy
399928f6ea ~修复小米软固化及自启动失败的bug 2026-01-27 09:30:50 +08:00
juewuy
13b291ccc7 ~修复setconfig()函数变更带来的bug 2026-01-27 09:19:19 +08:00
juewuy
f99d5f974b ~1.9.5a6.1 pkg 2026-01-26 21:37:01 +08:00
juewuy
692f2590d5 ~Improve UI 2026-01-26 21:20:31 +08:00
juewuy
243e51dd5c Merge branch 'master' into dev
# Conflicts:
#	ShellCrash.tar.gz
#	bin/version
#	version
2026-01-26 19:59:42 +08:00
juewuy
2b3720b8f3 ~1.9.4r1 pkg 2026-01-26 19:44:37 +08:00
juewuy
0261e5ecd4 Merge branch 'master' into dev
# Conflicts:
#	scripts/menu.sh
2026-01-26 19:39:33 +08:00
juewuy
6d904eb297 ~修复Wireguard网段会被公网防火墙拦截的bug 2026-01-26 19:18:39 +08:00
juewuy
d2d25a60eb ~bug fix 2026-01-26 19:13:53 +08:00
juewuy
5e58823cee ~优化实现 2026-01-26 19:11:39 +08:00
juewuy
215fc29c35 ~优化实现 2026-01-26 19:08:06 +08:00
juewuy
21366a0667 ~配置文件管理优化和bug修复 2026-01-26 19:07:38 +08:00
juewuy
6077061ba4 ~bug fix 2026-01-26 17:56:00 +08:00
juewuy
62a54a458a ~1.9.5a6 pkg 2026-01-25 21:32:31 +08:00
juewuy
e468129572 Merge branch 'master' into dev
# Conflicts:
#	ShellCrash.tar.gz
#	bin/version
#	version
2026-01-25 21:32:02 +08:00
juewuy
d00f558ae2 ~1.9.5b7 pkg 2026-01-25 21:31:09 +08:00
juewuy
60bee9039d Merge branch 'master' into dev 2026-01-25 21:27:09 +08:00
juewuy
acff8898a2 ~修复tailscale网段会被公网防火墙拦截的bug 2026-01-25 21:26:50 +08:00
juewuy
019ab1bd07 ~bug fix 2026-01-25 21:23:06 +08:00
juewuy
a71ca7c362 ~bug fix 2026-01-25 21:01:39 +08:00
juewuy
27d7b0cdf1 Merge branch 'master' into dev
# Conflicts:
#	scripts/menu.sh
2026-01-25 20:59:59 +08:00
juewuy
3ae53623d7 ~bug fix 2026-01-25 20:58:47 +08:00
juewuy
1211c48dbd Merge branch 'master' into dev
# Conflicts:
#	ShellCrash.tar.gz
#	bin/version
#	scripts/menu.sh
#	scripts/menus/7_gateway.sh
#	scripts/menus/9_upgrade.sh
#	scripts/menus/bot_tg_bind.sh
#	version
2026-01-25 20:46:36 +08:00
juewuy
d98501fe66 ~增加日志容量,取消60分钟以内定时任务的日志记录 2026-01-25 20:43:34 +08:00
juewuy
828d70e4f8 ~bug fix 2026-01-25 20:35:46 +08:00
juewuy
0014c5c32a ~bug fix
# Conflicts:
#	scripts/menu.sh
2026-01-25 20:32:51 +08:00
juewuy
961aeb5bb1 ~增加版本回退时需重新进入新手引导的机制
# Conflicts:
#	scripts/menus/9_upgrade.sh
2026-01-25 20:31:52 +08:00
juewuy
daee138365 ~修复部分小米路由自启时出现多个进程的bug 2026-01-25 20:29:02 +08:00
juewuy
9029a2ce82 ~优化bot_tg机器人绑定提示
# Conflicts:
#	scripts/menus/7_gateway.sh
#	scripts/menus/bot_tg_bind.sh
2026-01-25 20:28:33 +08:00
juewuy
219279c165 ~优化bot_tg机器人绑定提示 2026-01-25 20:18:12 +08:00
juewuy
89e6fe7faa ~修复部分小米路由自启时出现多个进程的bug 2026-01-25 20:06:09 +08:00
juewuy
64566495ff ~增加版本回退时需重新进入新手引导的机制 2026-01-25 20:02:15 +08:00
juewuy
4a1e49e1f0 ~重写配置备份还原功能,现在改为备份还原完整/configs目录 2026-01-25 19:54:39 +08:00
juewuy
08afce3500 ~bug fix 2026-01-25 19:51:36 +08:00
juewuy
ccbe2468b8 ~修改自定义内核类型排序 2026-01-25 19:28:10 +08:00
juewuy
7c91ab5c02 ~bug fix 2026-01-25 19:24:17 +08:00
juewuy
0ecfad2d2c ~现在安装时如指定了版本分支,在更新界面不再会显示未选择 2026-01-25 19:08:45 +08:00
juewuy
71e4816020 ~Change content_list() > list_box() 2026-01-25 18:57:43 +08:00
juewuy
f0eb2fc672 Merge pull request #1184 from sofia-riese/redesign-ddns
feat(ddns.sh): adapt new designs for more interfaces
2026-01-25 18:52:12 +08:00
sofia
323b8cf61c feat(ddns.sh): adapt new designs for more interfaces 2026-01-25 18:38:18 +08:00
juewuy
241d3f2335 Merge pull request #1183 from sofia-riese/redesign-tg
feat(bot_tg_bind.sh): adapt new designs for more interfaces
2026-01-25 17:25:59 +08:00
sofia
ca236f2651 feat(bot_tg_bind.sh): adapt new designs for more interfaces 2026-01-25 17:05:45 +08:00
juewuy
7f403992b6 ~修复管理配置文件功能的若干bug
~优化管理配置文件功能列表显示
~add content_list() for tui
2026-01-25 16:05:37 +08:00
juewuy
dc694f30c0 Merge pull request #1181 from sofia-riese/redesign-1
feat: redesign static text menu
2026-01-25 13:10:35 +08:00
sofia
5a5b688ad5 feat: redesign static text menu 2026-01-25 12:42:01 +08:00
sofia
b3fdf16591 Merge remote-tracking branch 'upstream/dev' into redesign-1 2026-01-25 00:05:27 +08:00
sofia
4e0417c951 update 2026-01-25 00:03:30 +08:00
juewuy
3759951575 ~1.9.5a5 pkg 2026-01-24 22:15:39 +08:00
juewuy
e03be1f184 ~修复版本号问题 2026-01-24 22:11:12 +08:00
juewuy
26fca6b359 ~完善配置文件管理功能,现在支持:
·导入管理各种订阅/节点链接,本地配置文件,本地base64文件
 ·单独订阅、本地文件通过providers生成配置文件
 ·单独订阅、节点通过Subconverter获取在线配置文件
 ·单独订阅、本地文件直接作为配置文件使用
 ·本地生成全部提供者,支持在线生成全部订阅、分享链接
 ·本地生成功能支持自定义健康检查/自动更新间隔、正则筛选及UA
2026-01-24 22:05:49 +08:00
juewuy
aec40082b1 Merge pull request #1179 from sofia-riese/redesign-uninstall
feat(uninstall.sh): redesign static text menu
2026-01-24 14:17:28 +08:00
sofia
b93a63d94a feat(uninstall.sh): redesign static text menu 2026-01-24 13:49:57 +08:00
juewuy
3dcdd8a676 Merge pull request #1176 from sofia-riese/redesign-main
feat(menu.sh): redesign static text menu
2026-01-24 11:32:40 +08:00
Sofia
58508966de chore(menu.sh): remove errornum() and use from common.sh 2026-01-24 10:27:54 +08:00
Sofia
3188d08b34 Merge branch 'dev' into redesign-main 2026-01-24 00:12:48 +08:00
sofia
022b78a4e3 feat(menu.sh): redesign static text menu 2026-01-24 00:02:35 +08:00
juewuy
a8f9aa4385 ~1.9.5a4 pkg 2026-01-24 00:01:06 +08:00
juewuy
52070fbba3 Merge branch 'dev' of https://github.com/juewuy/ShellCrash into dev 2026-01-24 00:00:17 +08:00
juewuy
ca72c5e1fc ~重写管理配置文件功能并拆分6_core_config.sh
~增加通用框架文件 common.sh
~修复在线生成配置文件时日志功能失效的bug
2026-01-24 00:00:05 +08:00
juewuy
48ad7723ad Merge pull request #1175 from sofia-riese/redesign-chore
chore: enhance interface display effects
2026-01-23 19:57:44 +08:00
sofia
60d945c3a2 chore: enhance interface display effects 2026-01-23 19:55:59 +08:00
juewuy
a082c68a7b Merge pull request #1173 from sofia-riese/redesign-1
feat(dns.sh): redesign static text menu
2026-01-23 18:13:17 +08:00
juewuy
601c419154 Merge pull request #1172 from sofia-riese/patch-1
fix(tui_layout.sh): apply font color
2026-01-23 18:13:00 +08:00
juewuy
3fe8f93500 Merge pull request #1174 from sofia-riese/redesign-2
feat(1_start.sh): redesign static text menu
2026-01-23 18:12:21 +08:00
sofia
ef07b31fd9 feat(1_start.sh): redesign static text menu 2026-01-23 18:10:35 +08:00
sofia
5647f60373 feat(dns.sh): redesign static text menu 2026-01-23 14:42:27 +08:00
Sofia
fed0bfeb90 feat(tui_layout.sh): identify line break "\n" 2026-01-23 14:34:35 +08:00
Sofia
358fd945f2 fix(tui_layout.sh): apply font color 2026-01-23 13:47:29 +08:00
juewuy
236fb8cd9a Merge pull request #1171 from sofia-riese/redesign-2
feat(2_settings.sh): redesign static text menu
2026-01-23 00:07:57 +08:00
sofia
a91cfc44ca feat(2_settings.sh): redesign static text menu 2026-01-22 23:57:57 +08:00
juewuy
9ca503ec82 Merge pull request #1170 from sofia-riese/redesign-4
feat(4_setboot.sh): redesign TUI
2026-01-22 13:46:33 +08:00
sofia
beab3386d2 feat(4_setboot.sh): redesign TUI 2026-01-22 13:04:52 +08:00
juewuy
8f60cc41e7 Merge pull request #1169 from sofia-riese/redesign-5
feat(5_task.sh): redesign TUI
2026-01-22 07:50:26 +08:00
sofia
89975bdfff feat(5_task.sh): redesign TUI 2026-01-22 01:19:25 +08:00
juewuy
a45bd9c0d1 ~修复分享链接被Tui切断的bug 2026-01-21 20:23:48 +08:00
juewuy
f4048b4b9c ~1.9.5a3 pkg 2026-01-21 19:42:12 +08:00
juewuy
8fd77bb666 ~crash -t命令增加强制调用tui-lite.sh机制
~更新界面列表及部分文字说明优化
2026-01-21 19:40:25 +08:00
juewuy
213eccc436 ~bug fix 2026-01-21 19:16:44 +08:00
juewuy
e8651591ff ~优化测试相关命令
~优化版本回退功能,现在支持回退到近期tags
2026-01-21 19:15:49 +08:00
juewuy
9b7c5e658c ~优化测试相关命令
~优化版本回退功能,现在支持回退到近期tags
~修复保守模式停止服务时未正确注销防火墙的bug
~修复小米设备因安装在u盘等导致自启命令不正确的bug

# Conflicts:
#	scripts/menu.sh
#	scripts/menus/9_upgrade.sh
2026-01-21 19:09:32 +08:00
juewuy
acf34714cc ~1.9.4b6 pkg 2026-01-21 19:06:12 +08:00
juewuy
56cb4a327f ~优化测试相关命令
~优化版本回退功能,现在支持回退到近期tags
~修复保守模式停止服务时未正确注销防火墙的bug
~修复小米设备因安装在u盘等导致自启命令不正确的bug
2026-01-21 19:05:40 +08:00
juewuy
a80c5b5c42 Merge pull request #1168 from sofia-riese/redesign-7
feat(7_gateway.sh): redesign TUI
2026-01-21 18:37:45 +08:00
sofia
382a9b7be3 Update 7_gateway.sh 2026-01-21 18:33:05 +08:00
sofia
fc247210cb Update 7_gateway.sh 2026-01-21 18:30:41 +08:00
juewuy
df6ea47e2e Merge pull request #1167 from sofia-riese/patch-2
fix(tui_layout.sh): attempt to fix character encoding issues
2026-01-21 14:38:33 +08:00
Sofia
41595bb643 Update tui_layout.sh 2026-01-21 14:23:29 +08:00
juewuy
25c0680e3a Merge pull request #1166 from sofia-riese/patch-1
fix(tui_layout.sh): resolve awk 'bad regex' error by using octal escape
2026-01-21 07:10:25 +08:00
Sofia
90682a06f4 fix(tui_layout.sh): resolve awk 'bad regex' error by using octal escape 2026-01-20 23:36:06 +08:00
juewuy
f7f39af5e3 ~1.9.4b5 pkg 2026-01-20 22:22:52 +08:00
juewuy
a73efc839e ~1.9.5a2 pkg 2026-01-20 22:22:00 +08:00
juewuy
8d82fcb88f Merge branch 'master' into dev 2026-01-20 22:20:34 +08:00
juewuy
f9be142dfa ~增加ChatID校验机制
~bug fix
2026-01-20 22:20:20 +08:00
juewuy
148251bb7f Merge branch 'master' into dev 2026-01-20 21:52:54 +08:00
juewuy
de7b57330e ~修复小闪存模式更新内核失败的bug
~修复部分情况下本机代理导致dns失效的bug
~增加Mihomo内核direct-nameserver默认配置
2026-01-20 21:51:57 +08:00
juewuy
8902a742a2 ~bug fix 2026-01-20 21:09:07 +08:00
juewuy
496467332a ~优化ReadMe 2026-01-20 21:05:56 +08:00
juewuy
7fc043ec49 ~Add tui_lite.sh
~Add tui switch menu
~chang double_line_break() > line_break()
2026-01-20 20:08:53 +08:00
juewuy
3d01ec827d 已修改 .github/workflows/core_easy_update.yaml
已修改        .github/workflows/update_singbox_core.yaml
2026-01-20 19:09:01 +08:00
juewuy
7336e73354 已添加 .github/workflows/core_easy_update.yaml 2026-01-20 18:43:40 +08:00
juewuy
ce4953ba75 调整Action 2026-01-20 18:17:09 +08:00
juewuy
cb0142785a Merge pull request #1163 from sofia-riese/redesign-8
feat(8_tools.sh): redesign TUI
2026-01-20 17:05:06 +08:00
sofia
4f5a037cc4 Update 8_tools.sh 2026-01-20 17:00:28 +08:00
juewuy
b39311d0a7 更新 bin_update.yml
修复面板解压失败
2026-01-20 13:52:51 +08:00
juewuy
0d002eb957 Merge pull request #1162 from sofia-riese/redesign
feat(9_upgrade.sh): redesign TUI
2026-01-20 10:07:00 +08:00
sofia
83139a4936 Update 9_upgrade.sh 2026-01-20 09:52:20 +08:00
sofia
dfaf2da168 feat(9_upgrade.sh): redesign TUI 2026-01-20 09:52:08 +08:00
juewuy
4f9d543e46 Merge pull request #1161 from sofia-riese/patch-1
refactor(set_ddns): replace recursion with while loop
2026-01-20 09:36:58 +08:00
Sofia
1b3e4892a1 refactor(set_ddns): replace recursion with while loop 2026-01-20 00:29:27 +08:00
juewuy
f18d0e4f6f Merge pull request #1159 from sofia-riese/patch-1
refactor(set_cust_host_ipv4): replace recursion with while loop
2026-01-19 14:23:23 +08:00
Sofia
7bf661ee3d refactor(set_cust_host_ipv4): replace recursion with while loop 2026-01-19 13:44:56 +08:00
juewuy
c98180fc4e Merge pull request #1158 from sofia-riese/patch-2
refactor(fw_filter_lan): replace recursion with while loop
2026-01-19 10:09:14 +08:00
Sofia
950afe955d Update fw_filter.sh 2026-01-19 10:05:01 +08:00
juewuy
48ee1ba07b Merge pull request #1157 from sofia-riese/patch-1
fix: fix an issue where colors were not displayed correctly due to automatic line breaks
2026-01-19 09:36:57 +08:00
Sofia
a4d2a3d7d6 Update tui_layout.sh 2026-01-19 09:10:21 +08:00
juewuy
d33fef974a Merge pull request #1156 from sofia-riese/patch-1
docs: add license instructions
2026-01-19 07:26:39 +08:00
Sofia
77687d4581 Merge branch 'juewuy:dev' into patch-1 2026-01-19 00:43:15 +08:00
juewuy
e25be4fafc Revert "feat(content_line): add automatic line break functionality"
This reverts commit 599dcdb15b.
2026-01-18 20:54:42 +08:00
juewuy
6b9f416315 Merge branch 'dev' of https://github.com/juewuy/ShellCrash into dev
# Conflicts:
#	ShellCrash.tar.gz
#	bin/version
#	version
2026-01-18 20:53:21 +08:00
juewuy
4dc170bf4a ~bug fix 2026-01-18 20:52:44 +08:00
juewuy
966b59692e ~bug fix 2026-01-18 20:52:02 +08:00
juewuy
8fe56b622e ~bug fix 2026-01-18 20:44:29 +08:00
juewuy
4f9ffbb7d7 ~bug fix 2026-01-18 20:27:45 +08:00
juewuy
01848bdeea Merge branch 'master' into dev 2026-01-18 20:26:55 +08:00
juewuy
100dee42be ~bug fix 2026-01-18 20:26:30 +08:00
Sofia
1dd48baca2 Update README_CN.md 2026-01-18 19:14:25 +08:00
Sofia
3f6b38b5fb Update README.md 2026-01-18 19:12:47 +08:00
Sofia
09d794083c Update README.md 2026-01-18 19:10:02 +08:00
juewuy
8b2bff3b03 ~bug fix 2026-01-18 19:06:59 +08:00
juewuy
bd5b9b315e ~1.9.5a1打包 2026-01-18 18:52:29 +08:00
juewuy
b5a314ce67 Merge branch 'master' into dev 2026-01-18 18:49:54 +08:00
juewuy
98a610eb58 ~1.9.4beta4打包 2026-01-18 18:49:32 +08:00
juewuy
8a9a294604 Merge branch 'dev' of https://github.com/juewuy/ShellCrash into dev 2026-01-18 18:46:28 +08:00
juewuy
de9c890559 Merge branch 'master' into dev 2026-01-18 18:46:15 +08:00
juewuy
02129b3109 ~适配更多模版 2026-01-18 18:46:03 +08:00
juewuy
023e0caeb9 ~bug fix 2026-01-18 18:30:40 +08:00
juewuy
d0aca38039 Merge pull request #1154 from sofia-riese/patch-1
refactor(set_common_ports): replace recursion with while loop
2026-01-18 18:25:09 +08:00
Sofia
7e3ec496be refactor(set_common_ports): replace recursion with while loop 2026-01-18 18:15:57 +08:00
juewuy
d023479daf Merge pull request #1153 from sofia-riese/patch-4
feat(content_line): add automatic line break functionality
2026-01-18 18:05:04 +08:00
Sofia
599dcdb15b feat(content_line): add automatic line break functionality 2026-01-18 17:59:51 +08:00
juewuy
48fd622ba2 ~Add i18n install set 2026-01-18 17:57:17 +08:00
juewuy
6aa56b0c29 ~Add install_en.sh 2026-01-18 17:49:29 +08:00
juewuy
bdc2505570 ~Add install_en.sh 2026-01-18 17:44:46 +08:00
juewuy
c72840d813 已修改 scripts/menu.sh 2026-01-18 17:33:26 +08:00
juewuy
e028260a65 Merge pull request #1092 from sofia-riese/patch-2
feat(9_upgrade): redesign TUI
2026-01-18 17:22:34 +08:00
juewuy
11498c1517 Merge pull request #1094 from sofia-riese/patch-3
docs: update English version README.md
2026-01-18 17:21:46 +08:00
juewuy
d26f724621 Merge pull request #1152 from sofia-riese/patch-1
refactor(set_fw_filter): replace recursion with while loop
2026-01-18 17:21:29 +08:00
Sofia
de3f4b4254 refactor(set_fw_filter): replace recursion with while loop 2026-01-18 16:02:29 +08:00
juewuy
477eb3d2aa Merge pull request #1151 from sofia-riese/patch-1
refactor(ddns.sh): replace recursion with while loop
2026-01-18 10:49:59 +08:00
Sofia
c52327a30c refactor(ddns.sh): replace recursion with while loop 2026-01-18 10:47:39 +08:00
juewuy
5d0a61f496 Merge pull request #1150 from sofia-riese/patch-1
refactor(load_ddns): replace recursion with while loop
2026-01-18 10:41:38 +08:00
Sofia
9ba5a687af refactor(load_ddns): replace recursion with while loop 2026-01-18 10:39:27 +08:00
juewuy
3232c73233 Merge pull request #1149 from sofia-riese/patch-1
refactor(dns.sh): replace recursion with while loop
2026-01-18 09:48:58 +08:00
Sofia
1d76570c2c refactor(dns.sh): replace recursion with while loop 2026-01-18 09:46:13 +08:00
juewuy
6dca739c3e Merge pull request #1148 from sofia-riese/patch-4
perf: optimize port validation with efficient grep usage
2026-01-18 09:25:53 +08:00
juewuy
0fb8c21c14 Merge pull request #1147 from sofia-riese/patch-1
refactor(set_shadowsocks): replace recursion with while loop
2026-01-18 09:25:25 +08:00
Sofia
180629c8dd perf: optimize port validation with efficient grep usage
- Use 'grep -q' to avoid unnecessary output and sub-shell usage
2026-01-18 09:14:43 +08:00
Sofia
b4bbaba73d refactor(set_shadowsocks): replace recursion with while loop 2026-01-18 09:03:44 +08:00
juewuy
588afd7381 Merge pull request #1146 from sofia-riese/fix_bug
fix: correct read option order (-r -p) to avoid invalid identifier error
2026-01-17 23:15:54 +08:00
Sofia
a6e26c0bd6 Merge branch 'juewuy:dev' into fix_bug 2026-01-17 23:06:23 +08:00
sofia
5ee05aafb3 fix bug 2026-01-17 23:04:55 +08:00
juewuy
056e50dea2 Merge branch 'dev' of https://github.com/juewuy/ShellCrash into dev 2026-01-17 22:58:05 +08:00
juewuy
6a0a31d76e ~优化install.sh set_crashdir.sh 2026-01-17 22:57:56 +08:00
juewuy
25e998c34a Merge pull request #1145 from sofia-riese/patch-1
refactor(setproxies): replace recursion with while loop
2026-01-17 22:06:50 +08:00
Sofia
013305e455 refactor(setproxies): replace recursion with while loop 2026-01-17 22:05:55 +08:00
juewuy
c4a7d7a005 Revert "docs(install): optimize prompts"
This reverts commit d708f0e113.

# Conflicts:
#	install.sh
2026-01-17 21:39:19 +08:00
juewuy
fa81312609 ~Add i18n switch menu 2026-01-17 21:34:10 +08:00
juewuy
9360363478 ~Add i18n switch menu 2026-01-17 21:32:06 +08:00
juewuy
db71fcd04a Merge branch 'dev' of https://github.com/juewuy/ShellCrash into dev 2026-01-17 21:12:20 +08:00
juewuy
7422a3f3c8 ~Add i18n support for dns.sh
~Fix i18n support for 2_settings.sh
2026-01-17 21:12:09 +08:00
juewuy
77f30626b3 Merge pull request #1144 from sofia-riese/patch-1
fix(tui_layout): handle missing and empty string parameters correctly
2026-01-17 20:23:07 +08:00
Sofia
e20b33046b fix(tui_layout): handle missing and empty string parameters correctly 2026-01-17 20:18:15 +08:00
juewuy
e99695a2f1 Merge branch 'dev' of https://github.com/juewuy/ShellCrash into dev 2026-01-17 20:09:21 +08:00
juewuy
42d9f6c0b7 Merge pull request #1143 from sofia-riese/patch-1
refactor(set_bot_tg): replace recursion with while loop
2026-01-17 20:09:10 +08:00
juewuy
040accdef0 ~Fix i18n support for 2_settings.sh 2026-01-17 20:08:11 +08:00
Sofia
f7b50209f0 refactor(set_bot_tg): replace recursion with while loop 2026-01-17 19:37:10 +08:00
juewuy
23040b3570 ~bug fix 2026-01-17 18:43:29 +08:00
juewuy
14b6118ee4 Merge pull request #1142 from sofia-riese/patch-4
refactor(setgroups): replace recursion with while loop
2026-01-17 17:41:11 +08:00
Sofia
66d848581a refactor(setgroups): replace recursion with while loop 2026-01-17 17:37:14 +08:00
juewuy
b98a996cb4 更新 bot_tg_service.sh 2026-01-17 17:29:32 +08:00
juewuy
1cef94d23c Merge pull request #1141 from sofia-riese/patch-1
refactor(forwhat): replace recursion with while loop
2026-01-17 17:27:21 +08:00
Sofia
18e3046aa4 refactor(forwhat): replace recursion with while loop 2026-01-17 17:18:17 +08:00
juewuy
0b8733f00e Merge pull request #1139 from sofia-riese/patch-5
feat(tui): add layout utilities for terminal UI formatting
2026-01-17 14:09:49 +08:00
Sofia
04c5f088ba update 2026-01-17 13:13:33 +08:00
Sofia
28de722560 update 2026-01-17 13:12:08 +08:00
juewuy
5223400684 Merge pull request #1138 from sofia-riese/patch-4
fix(4_setboot): fix some warnings from ShellCheck prompts
2026-01-17 13:01:19 +08:00
juewuy
24bff21259 Merge pull request #1137 from sofia-riese/patch-1
refactor(set_wireguard): replace recursion with while loop and fix some bug
2026-01-17 13:00:39 +08:00
Sofia
a3a8e9aa86 Update menu.sh 2026-01-17 12:55:02 +08:00
Sofia
0317d12e1d feat(tui): add layout utilities for terminal UI formatting
Prepare for future TUI modifications
2026-01-17 12:54:02 +08:00
Sofia
27aefb7699 fix(4_setboot): fix some errors from ShellCheck prompts 2026-01-17 12:27:38 +08:00
Sofia
bacdf4675f refactor(set_wireguard): replace recursion with while loop and fix some bug 2026-01-17 12:08:08 +08:00
juewuy
58dd51b483 Merge pull request #1134 from sofia-riese/patch-4
fix(5_task): add double quote to prevent word splitting
2026-01-16 22:25:41 +08:00
juewuy
ff4f8673fc Merge pull request #1133 from sofia-riese/patch-1
refactor(setrules): replace recursion with while loop
2026-01-16 22:24:49 +08:00
Sofia
0c9d110437 fix(5_task): add double quote to prevent word splitting
- Add double quote to prevent word splitting
- Format code with shfmt
2026-01-16 21:52:02 +08:00
Sofia
b3b72b4b85 refactor(setrules): replace recursion with while loop
- Replace recursion with while loop
- Add double quote to prevent word splitting
- Use grep -q instead of [ -n ... ] for rule match
2026-01-16 21:04:48 +08:00
juewuy
9c7bf11cfa Merge branch 'master' into dev 2026-01-16 20:15:44 +08:00
juewuy
c816d97893 ~bug fix 2026-01-16 20:15:26 +08:00
juewuy
c84a92b2e5 ~Add i18n support for 2_settings.sh 2026-01-16 20:08:01 +08:00
juewuy
0cb57d1d7b ~Add i18n support for 2_settings.sh 2026-01-16 19:59:31 +08:00
juewuy
329db0d9f2 Merge branch 'master' into dev 2026-01-16 18:40:05 +08:00
juewuy
48c60b8ea0 ~1.9.4beta3.2打包 2026-01-16 18:39:48 +08:00
juewuy
bd036da990 ~优化定时任务 2026-01-16 18:38:23 +08:00
juewuy
496e353a11 ~优化定时任务 2026-01-16 18:36:57 +08:00
juewuy
2ca471a361 Merge branch 'master' into dev
# Conflicts:
#	scripts/menus/8_tools.sh
2026-01-16 18:32:44 +08:00
juewuy
eee4f17947 ~bug fix 2026-01-16 18:32:16 +08:00
juewuy
ebf0186266 ~bug fix 2026-01-16 18:29:18 +08:00
juewuy
7d8279c9df Merge branch 'master' into dev 2026-01-16 18:26:13 +08:00
juewuy
461387eaac ~bug fix 2026-01-16 18:25:51 +08:00
juewuy
0c7cf39e29 Merge branch 'master' into dev
# Conflicts:
#	scripts/menus/7_gateway.sh
2026-01-16 18:19:43 +08:00
juewuy
da92996385 ~修复描述 2026-01-16 18:18:35 +08:00
juewuy
ed6b4432e7 Merge branch 'dev' of https://github.com/juewuy/ShellCrash into dev 2026-01-16 16:44:06 +08:00
juewuy
4e971176d2 Merge pull request #1132 from sofia-riese/patch-1
fix(1_start): add double quote to prevent word splitting
2026-01-15 21:26:58 +08:00
Sofia
63e6daca22 fix(1_start): add double quote to prevent word splitting 2026-01-15 21:22:15 +08:00
juewuy
d01b96bdb3 Merge branch 'master' into dev 2026-01-15 19:42:33 +08:00
juewuy
ba5a7a3a69 ~bug fix 2026-01-15 19:42:17 +08:00
juewuy
2461c93b9f ~回退pr修改 2026-01-15 19:10:08 +08:00
juewuy
70b5c22fc2 Merge branch 'dev' of https://github.com/juewuy/ShellCrash into dev 2026-01-15 19:07:26 +08:00
juewuy
ff278298c9 Merge branch 'master' into dev
# Conflicts:
#	scripts/libs/sb_endpoints.sh
2026-01-15 19:04:13 +08:00
juewuy
c626085679 ~修复ts和wg启动失败的bug 2026-01-15 19:03:25 +08:00
juewuy
8cf3ab2228 Merge pull request #1131 from sofia-riese/patch-4
fix(4_setboot): add double quote to prevent word splitting
2026-01-15 18:55:21 +08:00
juewuy
5cd8122c46 ~bug fix 2026-01-15 18:53:32 +08:00
juewuy
3907be4c3f ~bug fix 2026-01-15 18:53:03 +08:00
juewuy
b5cfedf3dc Merge branch 'dev' of https://github.com/juewuy/ShellCrash into dev 2026-01-15 18:49:15 +08:00
Sofia
5ccf102791 fix(4_setboot): add double quote to prevent word splitting 2026-01-15 18:47:53 +08:00
juewuy
0fad4c0d3e ~修复自动编译失败的问题,arm64和amd64内核upx压缩版本改为5.1.0 2026-01-15 18:47:48 +08:00
juewuy
bdd13aa91b Merge pull request #1130 from sofia-riese/patch-1
refactor(set_tailscale): replace recursion with while loop
2026-01-15 18:43:49 +08:00
Sofia
b6d19a7ac4 refactor(set_tailscale): replace recursion with while loop 2026-01-15 18:41:07 +08:00
juewuy
e460df9ca6 Merge pull request #1129 from sofia-riese/patch-1
perf(install): enhance execution efficiency
2026-01-15 18:34:35 +08:00
juewuy
b3d2c8af69 ~修复自动编译失败的问题,arm64和amd64内核upx压缩版本改为5.1.0 2026-01-15 18:32:03 +08:00
Sofia
635dcd7ee3 perf(install): enhance execution efficiency 2026-01-15 18:22:35 +08:00
juewuy
cb38a98332 Merge branch 'master' into dev 2026-01-15 18:05:27 +08:00
juewuy
feb3c2a421 ~1.9.4beta3打包 2026-01-15 18:05:08 +08:00
juewuy
8ea6a38213 Merge branch 'master' into dev 2026-01-15 18:04:26 +08:00
juewuy
9aa6f3d5bb ~增加wg和ts配置生成检测机制防止文件冲突
~bug fix
2026-01-15 18:04:13 +08:00
juewuy
5154339546 Merge pull request #1128 from sofia-riese/patch-6
refactor(set_fw_wan): replace recursion with while loop
2026-01-15 17:06:30 +08:00
juewuy
2cad4ec818 Merge pull request #1126 from sofia-riese/patch-5
style(8_tools): format code with shfmt
2026-01-15 17:05:49 +08:00
juewuy
4c16236823 Merge pull request #1125 from sofia-riese/patch-1
fix(5_task): add double quote to prevent word splitting
2026-01-15 17:04:37 +08:00
juewuy
422db97e87 Merge pull request #1114 from sofia-riese/patch-4
refactor(set_adv_config): replace recursion with while loop
2026-01-15 17:04:09 +08:00
Sofia
174cbabb93 refactor(set_fw_wan): replace recursion with while loop 2026-01-15 16:14:33 +08:00
Sofia
a5668dd94b style: format code 2026-01-15 15:35:19 +08:00
Sofia
16e3e7a489 fix(5_task): add double quote to prevent word splitting 2026-01-15 14:05:14 +08:00
Sofia
31ea92516f Merge branch 'juewuy:dev' into patch-3 2026-01-15 03:01:19 +08:00
Sofia
e66bd832e1 Merge branch 'dev' into patch-2 2026-01-15 03:00:25 +08:00
Sofia
7422f5dcc3 Merge branch 'juewuy:dev' into patch-4 2026-01-15 02:53:11 +08:00
Sofia
82f5fce989 repair accidental deletion operation 2026-01-15 02:49:01 +08:00
Sofia
3977565ad1 fix: revise return logic 2026-01-15 02:36:43 +08:00
juewuy
281595f79f Merge pull request #1123 from sofia-riese/patch-1
fix: format code and add double quote to prevent word splitting
2026-01-14 21:04:09 +08:00
Sofia
602f3e2890 fix: add double quote to prevent globbing and word splitting 2026-01-14 20:52:22 +08:00
juewuy
e048264d9e Merge pull request #1122 from sofia-riese/patch-1
refactor: replace recursion with while loop in main_menu
2026-01-14 20:31:14 +08:00
Sofia
7c3039ea68 refactor: replace recursion with while loop in main_menu 2026-01-14 20:28:06 +08:00
juewuy
690db2fe73 ~Add i18n support for 1_start.sh 2026-01-14 20:20:25 +08:00
juewuy
26831994b1 Merge branch 'master' into dev 2026-01-14 19:54:11 +08:00
juewuy
88dffde53c ~1.9.4beta2打包 2026-01-14 19:53:12 +08:00
juewuy
f9af59a7a9 Merge branch 'master' into dev 2026-01-14 19:52:30 +08:00
juewuy
06656b5694 ~尝试修复华硕设备关闭ssh时进程注销的bug 2026-01-14 19:52:19 +08:00
juewuy
617b8cf4b8 Merge branch 'master' into dev
# Conflicts:
#	scripts/menus/8_tools.sh
2026-01-14 19:26:07 +08:00
juewuy
e3789ea1ce ~修复新手引导死循环的bug 2026-01-14 19:24:58 +08:00
juewuy
e545b728b5 ~修复本地生成配置文件时默认模版报错的bug 2026-01-14 19:19:51 +08:00
juewuy
f833bb9ce7 ~修复本地生成配置文件时默认模版报错的bug 2026-01-14 19:09:39 +08:00
juewuy
22b8e04717 Merge branch 'master' into dev 2026-01-14 19:03:02 +08:00
juewuy
328466584b ~修复未安装内核时本地生成配置失败的bug 2026-01-14 19:02:44 +08:00
juewuy
48fee3d36d Merge branch 'master' into dev
# Conflicts:
#	scripts/menus/2_settings.sh
2026-01-14 18:56:17 +08:00
juewuy
893ddd7268 ~优化默认ipv4路由网段获取机制 2026-01-14 18:54:09 +08:00
juewuy
27906ee244 Merge branch 'master' into dev 2026-01-14 18:49:36 +08:00
juewuy
aef509de62 ~增加自启检测,修复反复自启导致死机循环的bug
~优化本地ipv4路由网段获取,修复Tailscale通告相关问题
~修复由于公网防火墙导致的本机及容器代理查询dns失败的相关bug
~修复entware环境兼容问题
~修复部分版本wget命令兼容问题
~修复保存面板节点功能相关bug
~修复singbox内核禁用配置覆写后启动失败的bug
2026-01-14 18:49:02 +08:00
juewuy
b2be8ab3fd Merge pull request #1121 from sofia-riese/redesign
style: redesign the install script interface
2026-01-14 17:05:28 +08:00
Sofia
08f346a6f4 fix: use quotation marks to prevent word splitting 2026-01-13 12:51:01 +08:00
Sofia
739ee5d22c Merge branch 'dev' into patch-2 2026-01-13 10:06:11 +08:00
Sofia
2d7fbdb443 style: update 2026-01-13 10:02:29 +08:00
Sofia
3797d95174 docs: update README.md
Updated the English README.md based on the latest version of the Simplified Chinese README.md document.
2026-01-12 22:57:53 +08:00
Sofia
7c33c24f80 style: redesign the install script interface 2026-01-12 22:31:03 +08:00
juewuy
0860d177a1 Merge pull request #1120 from DustinWin/dev
优化 sing-box 域名嗅探覆写和规则覆写
2026-01-12 21:36:40 +08:00
DustinWin
0cf5e798b3 优化 sing-box 域名嗅探覆写和规则覆写 2026-01-12 21:12:16 +08:00
juewuy
0e6471c155 Merge pull request #1118 from sofia-riese/patch-1
refactor(set_core_config_link): replace recursion with while loop
2026-01-12 17:47:05 +08:00
juewuy
cf3b94424c Merge pull request #1119 from Maozai-Teng/dev
小修小补~
2026-01-12 17:46:48 +08:00
小小小猫仔
e4efd439bf 小修小补~ 2026-01-12 06:38:02 +08:00
小小小猫仔
545ce0da20 小修小补~ 2026-01-12 06:37:35 +08:00
Sofia
d630f7534e refactor(set_core_config_link): replace recursion with while loop 2026-01-12 02:06:05 +08:00
juewuy
ffce704f5e Merge pull request #1117 from sofia-riese/patch-6
docs(readme_cn): add hints
2026-01-11 20:46:37 +08:00
Sofia
a1a9b10a85 docs(readme_cn): add hints 2026-01-11 19:24:19 +08:00
juewuy
98adc4dad5 Merge pull request #1116 from sofia-riese/patch-1
refactor(set_core_config): replace recursion with while loop
2026-01-11 18:23:48 +08:00
Sofia
56d8bbadc2 refactor(set_core_config): replace recursion with while loop 2026-01-11 17:09:11 +08:00
Sofia
7676a3f607 refactor(set_adv_config): replace recursion with while loop 2026-01-11 12:51:18 +08:00
juewuy
55b8266dfd Merge pull request #1113 from sofia-riese/patch-4
refactor(setproviders): replace recursion with while loop
2026-01-11 09:46:17 +08:00
Sofia
a544637651 refactor(setproviders): replace recursion with while loop 2026-01-11 09:24:13 +08:00
juewuy
51ff53f1d7 Merge pull request #1112 from sofia-riese/patch-6
refactor(set_ipv6): replace recursion with while loop
2026-01-11 08:09:08 +08:00
juewuy
97de3c8fe8 Merge pull request #1111 from sofia-riese/patch-4
refactor(gateway): replace recursion with while loop
2026-01-11 08:08:48 +08:00
Sofia
da11c319b8 refactor(set_ipv6): replace recursion with while loop 2026-01-11 01:45:10 +08:00
Sofia
d797838378 refactor(gateway): replace recursion with while loop 2026-01-11 01:37:56 +08:00
juewuy
093fffee05 Merge pull request #1110 from DustinWin/dev
全分组新增奈飞和油管规则
2026-01-10 22:35:16 +08:00
DustinWin
ac60ba8001 全分组新增奈飞和油管规则 2026-01-10 22:05:57 +08:00
juewuy
2e150ca9d9 Merge pull request #1108 from sofia-riese/patch-4
refactor(task_manager): replace recursion with while loop
2026-01-10 19:42:33 +08:00
Sofia
0712905fbe refactor(task_manager): replace recursion with while loop 2026-01-10 17:25:32 +08:00
juewuy
10e50dc244 Merge pull request #1107 from sofia-riese/patch-1
docs(install): optimize prompts
2026-01-10 16:17:16 +08:00
Sofia
d708f0e113 docs(install): optimize prompts 2026-01-10 14:03:28 +08:00
juewuy
ff0fa89717 Merge pull request #1106 from sofia-riese/patch-1
refactor: format code and replace recursion with while loop in set_alias
2026-01-10 11:38:59 +08:00
Sofia
24ed96a618 refactor: formatter code and replace recursion with while loop in set_alias 2026-01-10 11:28:02 +08:00
juewuy
3e331d786f Merge pull request #1105 from sofia-riese/patch-1
docs: change emoji to GitHub emoji markup and standardize naming
2026-01-10 09:37:19 +08:00
juewuy
cfa9c58451 Merge pull request #1104 from sofia-riese/patch-7
refactor: replace recursion with while loop in setdir
2026-01-10 09:36:55 +08:00
Sofia
26ae84afd5 docs: change emoji to GitHub emoji markup and standardize naming 2026-01-10 09:15:59 +08:00
Sofia
85396a6b5d refactor: replace recursion with while loop in setdir 2026-01-10 09:04:56 +08:00
juewuy
3147bb650d Merge pull request #1101 from sofia-riese/patch-1
refactor: replace recursion with while loop in set_redir_mod
2026-01-10 08:51:39 +08:00
juewuy
b065a7d4c8 Merge pull request #1102 from sofia-riese/patch-4
docs: beautify the README_CN document layout
2026-01-10 08:50:09 +08:00
juewuy
903d0592ce Merge pull request #1103 from sofia-riese/patch-5
refactor: replace recursion with while loop in setcustcore
2026-01-10 08:49:14 +08:00
Sofia
d4646030a5 refactor: replace recursion with while loop in setcustcore 2026-01-09 22:30:28 +08:00
Sofia
263792d0cf docs: change emoji to github markdown emoji markup 2026-01-09 21:50:38 +08:00
Sofia
ad969c9f27 docs: beautify the README_CN document layout 2026-01-09 21:44:55 +08:00
Sofia
ea0bec152e refactor: replace recursion with while loop in set_redir_mod 2026-01-09 19:23:32 +08:00
juewuy
167ab30b29 Merge pull request #1099 from sofia-riese/patch-1
refactor: replace recursion with while loop in set_vmess
2026-01-09 14:18:56 +08:00
juewuy
4760708248 Merge pull request #1100 from sofia-riese/patch-4
fix: correct VmRSS unit conversion and simplify logic
2026-01-09 14:17:43 +08:00
Sofia
64de8c8146 fix: correct VmRSS unit conversion and simplify logic 2026-01-09 13:33:15 +08:00
Sofia
4003a80c56 refactor: replace recursion with while loop in set_vmess 2026-01-09 10:10:25 +08:00
juewuy
2f796af178 Merge pull request #1098 from Maozai-Teng/dev
谁能想到日本节点里面可以混进去一个尼日利亚呢~
2026-01-09 09:55:19 +08:00
小小小猫仔
1c4b936722 谁能想到日本节点里面可以混进去一个尼日利亚呢~ 2026-01-09 09:50:55 +08:00
小小小猫仔
75302adb1c 谁能想到日本节点里面可以混进去一个尼日利亚呢~ 2026-01-09 09:50:39 +08:00
juewuy
912f281730 Merge pull request #1093 from sofia-riese/patch-1
refactor: replace recursion with while loop in settings
2026-01-09 08:29:56 +08:00
juewuy
270a5d68ab Merge pull request #1095 from sofia-riese/patch-4
docs: enhance the table display in README_CN.md
2026-01-09 08:26:37 +08:00
juewuy
1e76dc11e8 Merge pull request #1096 from sofia-riese/patch-5
refactor: replace recursion with while loop in override
2026-01-09 08:24:30 +08:00
juewuy
cd7de527fa Merge pull request #1097 from sofia-riese/patch-6
fix: solve recursion problem and improve the execution logic order
2026-01-09 08:23:45 +08:00
Sofia
b428d4c786 fix: potential risks of forced withdrawal midway 2026-01-09 06:41:40 +08:00
Sofia
f150d14f80 fix: solve the recursion problem 2026-01-09 06:34:05 +08:00
Sofia
492a2fe898 refactor: replace recursion with while loop in override 2026-01-09 00:55:19 +08:00
Sofia
a0df852611 docs: enhance the table display in README_CN.md 2026-01-08 22:04:42 +08:00
Sofia
a8f42ba443 docs: updated English version README.md
Referencing the Simplified Chinese README.md file, update the English version of README.md and improve formatting and minor wording.

I don't speak Mandarin, so please excuse any translation inaccuracies.
2026-01-08 21:52:14 +08:00
Sofia
b93ac17f2e refactor: replace recursion with while loop in settings 2026-01-08 20:48:10 +08:00
juewuy
da30e623ce ~拆分流量过滤和新手引导文件 2026-01-08 19:16:13 +08:00
juewuy
75b69e91b6 ~Add en support( Use [echo en > "$CRASHDIR"/configs/i18n.cfg] to test ! ) 2026-01-08 18:53:14 +08:00
juewuy
2e1744a993 ~Add i18n support (only menu.sh) 2026-01-08 18:46:41 +08:00
juewuy
6b34654705 Merge branch 'dev' of https://github.com/juewuy/ShellCrash into master 2026-01-08 17:32:14 +08:00
juewuy
abfa3049b3 ~1.9.4beta1.1打包 2026-01-08 17:31:51 +08:00
juewuy
d98f6ccef5 ~Tailscale通告网段改为使用透明路由ipv4网段
~bug fix
2026-01-08 17:31:17 +08:00
juewuy
bcfc55b89b Merge pull request #1091 from sofia-riese/patch-1
refactor: replace recursion with while loop in task_menu
2026-01-08 16:52:46 +08:00
Sofia
233b75b6e2 style: improve and unify the user interface 2026-01-08 15:59:53 +08:00
Sofia
9383b69a1a refactor: replace recursion with while loop in task_menu 2026-01-08 13:57:15 +08:00
juewuy
f72192e801 Merge branch 'dev' into master
# Conflicts:
#	ShellCrash.tar.gz
#	bin/clashfm.tar.gz
#	bin/version
#	version
2026-01-08 10:14:27 +08:00
juewuy
2c5dfe04c8 ~1.9.4beta1打包 2026-01-08 10:12:18 +08:00
juewuy
8ef30efa31 ~bug fix 2026-01-08 10:10:58 +08:00
juewuy
6d1b2a0a26 Merge pull request #1089 from sofia-riese/patch-1
refactor: replace recursion with while loop in setboot
2026-01-08 09:15:10 +08:00
juewuy
2619b0991c Merge pull request #1088 from Maozai-Teng/dev
修复自动选择可能会选到“剩余流量:xxx”、“距离下次重置:xxx”这种垃圾节点
2026-01-08 09:14:03 +08:00
Sofia
b636b49eb6 refactor: replace recursion with while loop in setboot 2026-01-08 00:19:36 +08:00
小小小猫仔
5f3cade963 Add files via upload 2026-01-07 22:25:06 +08:00
小小小猫仔
60747987e9 Add files via upload 2026-01-07 22:24:46 +08:00
小小小猫仔
e42182cde6 修复自动选择可能会选到“剩余流量:xxx”、“距离下次重置:xxx”这种垃圾节点
修复自动选择可能会选到“剩余流量:xxx”、“距离下次重置:xxx”这种垃圾节点
2026-01-07 22:12:55 +08:00
小小小猫仔
26130510fa 修复自动选择可能会选到“剩余流量:xxx”、“距离下次重置:xxx”这种垃圾节点
修复自动选择可能会选到“剩余流量:xxx”、“距离下次重置:xxx”这种垃圾节点
2026-01-07 22:12:29 +08:00
juewuy
5032cf6d8b ~1.9.3alpha8打包 2026-01-07 20:35:08 +08:00
juewuy
1c2474cf9e ~增加ecs优化功能 2026-01-07 20:23:56 +08:00
juewuy
0a0e5c0af9 ~增加ecs优化功能 2026-01-07 20:17:36 +08:00
juewuy
43cf4a914b ~重写常用端口过滤功能 2026-01-07 18:21:04 +08:00
juewuy
236292ac9f Merge pull request #1087 from sofia-riese/patch-2
Corrects potential errors when filenames are separated by spaces
2026-01-07 17:52:43 +08:00
juewuy
ecb10510cf Merge pull request #1086 from sofia-riese/patch-1
Keep addressing function self-invocation
2026-01-07 17:51:34 +08:00
Sofia
5306c8d3da Correct potential errors 2026-01-07 17:25:44 +08:00
Sofia
45b12fc70b Correct potential errors 2026-01-07 17:21:04 +08:00
Sofia
0b8bf53299 Keep addressing function self-invocation 2026-01-07 15:44:58 +08:00
juewuy
333a553b28 Merge pull request #1085 from sofia-riese/patch-1
Continue to address the issue of function self-invocation
2026-01-07 13:44:59 +08:00
Sofia
364fd54ced Continue to address the issue of function self-invocation 2026-01-07 12:30:14 +08:00
juewuy
2e85085cf7 Merge pull request #1084 from sofia-riese/patch-1
Fix tar extraction and grep command syntax
2026-01-07 11:12:34 +08:00
juewuy
8cda75e055 Merge pull request #1083 from sofia-riese/patch-5
Continue to address the issue of function self-invocation
2026-01-07 11:12:01 +08:00
juewuy
22cd7766cd ~增加单独指定dns劫持端口的功能(用于搭配第三方DNS服务) 2026-01-07 11:11:17 +08:00
juewuy
27dfc69f50 ~增加单独指定dns劫持端口的功能(用于搭配第三方DNS服务) 2026-01-07 11:10:45 +08:00
Sofia
ef3ff50fbf Fix tar extraction and grep command syntax 2026-01-07 10:37:08 +08:00
juewuy
f46cdade4d ~改为统一使用ON/OFF来表示功能开启关闭状态 2026-01-07 10:16:39 +08:00
Sofia
1d7be3a3a0 Continue to address the issue of function self-invocation 2026-01-07 09:58:56 +08:00
juewuy
098a70c067 ~1.9.3alpha7.3打包 2026-01-07 09:34:47 +08:00
juewuy
3770a0ebaf Merge branch 'dev' of https://github.com/juewuy/ShellCrash into dev 2026-01-07 09:30:44 +08:00
juewuy
981d6f7ec0 ~兼容调整 2026-01-07 09:30:27 +08:00
juewuy
496a10264a Merge pull request #1080 from sofia-riese/patch-1
Fix syntax errors
2026-01-07 01:16:27 +08:00
juewuy
cca59fe5d2 Merge pull request #1081 from sofia-riese/patch-2
Change shell type
2026-01-07 01:15:51 +08:00
Sofia Riese
a48ad916d2 Change shell type 2026-01-06 23:08:21 +08:00
Sofia Riese
d3f751e876 Correcting syntax errors 2026-01-06 22:20:49 +08:00
juewuy
50351fe6dc ~1.9.3alpha7.2打包 2026-01-06 21:27:26 +08:00
juewuy
7c8b0874bd ~优化ddns脚本 2026-01-06 21:26:22 +08:00
juewuy
3dec4a0d65 ~优化屏蔽quic实现机制,修复bug 2026-01-06 15:58:51 +08:00
juewuy
3772593f66 ~检查更新流程优化
~padavan自启优化
~部分界面文本优化
~bug fix
2026-01-06 14:51:18 +08:00
juewuy
93ac1b1da9 ~优化dir_avail函数 2026-01-06 13:45:20 +08:00
juewuy
0e9a14cc9d Merge pull request #1079 from ruth-hale/patch-7
Fix path for clashdb.tar.gz extraction
2026-01-06 13:26:54 +08:00
juewuy
2ef2a3e4ec Merge pull request #1078 from ruth-hale/patch-6
Refactor dir_avail function
2026-01-06 13:26:17 +08:00
juewuy
f218be0ff5 Merge pull request #1074 from ruth-hale/patch-4
Continue replace self-invoked with a while true loop
2026-01-06 13:25:31 +08:00
nested-universe
d0c0fe63dc Fix path for clashdb.tar.gz extraction 2026-01-05 18:27:53 +08:00
nested-universe
4360f6a702 Refactor dir_avail function
#### **1. Execution Efficiency**
* **Optimized Execution:** Streamlined from 4 external processes to just 2 (`df` and `awk`) by eliminating complex matrix transposition loops and string matching, significantly boosting execution speed and reducing overhead.

#### **2. Readability & Maintainability**
* **Clean Code:** Replaced 3 lines of convoluted logic with a single, clear pipeline.

#### **3. Robustness**
* **Anti-Wrapping:** The `-P` flag ensures the output stays on one line, preventing errors caused by long filesystem names that usually break `df` formatting.
* **Safe Defaults:** Uses `${1:-.}` to gracefully handle cases where no directory path is provided.
* **Dynamic Column Targeting:** Uses `$(NF-2)` to locate the "Available" column by position instead of fragile keyword filtering (e.g., "Available" or "可用"). This ensures locale-independence and correctly identifies the space value even if filesystem names contain spaces or if the system language changes.This is more robust than fixed column numbers because it correctly identifies the space value even if the filesystem name contains spaces or if the system adds extra trailing info.

#### **4. Seamless Compatibility**
* **Drop-in Replacement:** Fully supports your existing call patterns.
* **Zero Refactoring:** No changes are needed in the rest of your script to switch to this version.
2026-01-03 11:06:58 +08:00
juewuy
8faeec6cd2 Merge pull request #1077 from nested-universe/patch-5
Fix installation alias selection
2026-01-03 09:28:31 +08:00
nested-universe
8632dd9cb1 Change shebang to use env for bash 2026-01-03 09:26:50 +08:00
nested-universe
e57ae68396 Fix installation alias selection 2026-01-03 09:21:57 +08:00
juewuy
6108f66acc 更新 compose.yml 2026-01-02 19:26:53 +08:00
juewuy
5eb7f0988b 更新 README.md 2026-01-02 19:26:28 +08:00
nested-universe
3b4f3220dc Continue replace self-invoked with a while true loop
Currently, there appears to be no large-scale error.
So, keep going.
2026-01-02 17:33:32 +08:00
juewuy
dc1bf88840 更新 compose.yml 2026-01-02 15:47:05 +08:00
juewuy
fd9593f536 fix 2026-01-02 11:29:06 +08:00
juewuy
40a01428a5 ~调整内核下载功能
~bug修复
~找回误删的防止dnsmasq重定向功能
2026-01-02 11:28:27 +08:00
juewuy
b35f483652 fix 2026-01-02 11:19:29 +08:00
juewuy
2cfb2e5c08 已修改 .github/workflows/core_auto_update.yml 2026-01-02 11:15:59 +08:00
juewuy
7e1e7fa98d ~调整自动编译 2026-01-02 11:12:33 +08:00
juewuy
4238c7d433 已修改 .github/workflows/update_singbox_core.yaml 2026-01-02 11:06:36 +08:00
juewuy
7b07509887 ~优化alpha版本号为当前日期 2026-01-02 10:54:12 +08:00
juewuy
7e51c8bec0 ~仅在tar.gz包时变更版本号 2026-01-02 10:13:13 +08:00
juewuy
4b12ae7a28 ~增加"match_only": true分支特性 2026-01-02 10:06:41 +08:00
juewuy
6979ba9c83 ~upx压缩改为默认压缩率 2026-01-02 09:57:25 +08:00
juewuy
ea92f3e701 ~1.9.3alpha7打包 2026-01-01 15:54:04 +08:00
juewuy
760458cd58 ~修复zsh环境安装报错
~修复singbox内核ss入站无法生效的bug
2026-01-01 15:53:20 +08:00
juewuy
849fc928ed Merge branch 'dev' of https://github.com/juewuy/ShellCrash into dev 2026-01-01 15:41:40 +08:00
juewuy
ecca342893 ~修复crontab报错
~部分细节调整
2026-01-01 15:38:26 +08:00
juewuy
f83c46a99a Merge pull request #1070 from nested-universe/patch-3
Continue replace self-invoked with a while true loop
2026-01-01 14:53:29 +08:00
juewuy
389a24c139 Merge pull request #1068 from Maozai-Teng/dev
重要更新,之前忘记给private加直连了_(:3」 ∠)_
2026-01-01 14:48:24 +08:00
nested-universe
ea2a56f871 Continue replace self-invoked with a while true loop
- Use CASE statements instead of if-elif statements.
- Replace self-invoked with a while true loop.
- Wrap the inner function outside the parent function to prevent duplicate declarations caused by the while true loop.
2026-01-01 14:45:37 +08:00
juewuy
4f31373c5f ~增加3种不同的内核压缩方式,并对应不同版本分支 2026-01-01 14:19:43 +08:00
juewuy
26567c0862 已修改 .github/workflows/update_singbox_core.yaml 2026-01-01 14:03:10 +08:00
juewuy
a4363080bb 已修改 .github/workflows/update_singbox_core.yaml 2026-01-01 14:02:35 +08:00
juewuy
4eb4ac5871 ~改为按输入的压缩类型进行压缩 2026-01-01 13:42:05 +08:00
小小小猫仔
5158b36b1a 重要更新,之前忘记给private加直连了_(:3」 ∠)_
重要更新,之前忘记给private加直连了_(:3」 ∠)_
2026-01-01 13:37:11 +08:00
juewuy
ba1bd75666 ~修复upx被上传到github的bug 2026-01-01 13:04:43 +08:00
juewuy
4cdcb39f86 ~增加内核upx压缩 2026-01-01 12:58:05 +08:00
juewuy
e6ef71510e Update update_meta_core.yaml 2026-01-01 12:22:09 +08:00
juewuy
6324cee884 Update update_meta_core.yaml 2026-01-01 12:15:34 +08:00
juewuy
24d7dda41e Update update_meta_core.yaml 2026-01-01 11:34:56 +08:00
juewuy
eb97732930 已修改 .github/workflows/update_meta_core.yaml 2026-01-01 11:30:40 +08:00
juewuy
7c01df50fe ~增加upx压缩 2026-01-01 11:18:38 +08:00
juewuy
5aafe92198 ~调整Tailscale的缓存目录为安装目录,增加设备名称设置选项
~修复部分设备开机初始化失败的bug
~部分代码细节优化
2026-01-01 10:43:25 +08:00
juewuy
abb90eb6f0 修复auto_start.sh脚本调用失败 2026-01-01 08:13:24 +08:00
juewuy
69acd4ce7a Merge branch 'dev' of https://github.com/juewuy/ShellCrash into dev 2025-12-31 21:15:05 +08:00
juewuy
5e27b3fbd6 ~修复默认dns启动报错 2025-12-31 21:14:55 +08:00
juewuy
7f9d256294 Merge pull request #1065 from nested-universe/patch-2
Continue replace self-invoked with a while true loop
2025-12-31 20:54:38 +08:00
nested-universe
e655259d14 Continue replace self-invoked with a while true loop
- replace self-invoked with a while true loop。
- Wrap the inner function outside the parent function to prevent duplicate declarations caused by the while true loop.
2025-12-31 20:45:59 +08:00
juewuy
a86c64cd86 ~1.9.3alpha6打包 2025-12-31 20:45:23 +08:00
juewuy
639557be27 Merge branch 'dev' of https://github.com/juewuy/ShellCrash into dev 2025-12-31 20:44:31 +08:00
juewuy
08fc32d63e ~优化vmess入站功能,增加对自定义混淆host的配置存档
~优化Tailscale启用exitnode功能时的文字提示
~增加对无法自动获取lan网段设备的提示信息
~尝试修复部分设备定时任务报错
~尝试调整tun模式下屏蔽quic的防火墙工作机制
~修复重新进入新手引导会覆盖singbox内核为meta内核的bug
~修复公网防火墙放行端口在较新版本openwrt上未生效的bug
2025-12-31 20:44:21 +08:00
juewuy
442d9f8401 Merge pull request #1064 from Maozai-Teng/dev
增加global
2025-12-31 17:23:30 +08:00
小小小猫仔
963da8b15c 增加global
增加global
2025-12-31 17:22:07 +08:00
juewuy
6fe1938809 ~优化安装命令,兼容dash 2025-12-31 15:15:33 +08:00
juewuy
805d75720f 已修改 scripts/menus/dns.sh 2025-12-31 15:08:37 +08:00
juewuy
ebba797473 ~增加小米设备对autossh脚本的兼容
~增加小米设备/data/auto_start.sh文件,用于自定义开机启动项
~增加Mihomo内核默认启用统一延迟功能
~优化默认DNS,现在会默认使用localhost(如果可用)而不是阿里dns
~优化子菜单加载效率
~优化部分设备的tun加载流程,修复因为未加载tun模块而导致的启动报错
~优化dns界面显示
~修复因为文件拆分路径改变导致的加载失败的一系列bug
~修复局域网过滤白名单失效的bug(需要重新启用)
~修复自定义入站启用失败的bug
~修复前台测试内核运行命令报错的bug
~修复卸载时的意外报错
2025-12-31 15:07:21 +08:00
juewuy
69aa869dcd Merge pull request #1060 from nested-universe/patch-1
Improve upgrade function
2025-12-31 14:33:35 +08:00
nested-universe
aedcfa7403 Add Module Load Guard
Prevents redundant script loading by using a conditional flag to ensure the module is initialized only once.
2025-12-31 14:30:33 +08:00
juewuy
3d29ba885d Merge pull request #1063 from Maozai-Teng/dev
ShellCrash_RS_Full_BanAds 全面适配 sing-box
2025-12-31 13:44:11 +08:00
小小小猫仔
cbd028e6b0 ShellCrash_RS_Full_BanAds 全面适配 sing-box
ShellCrash_RS_Full_BanAds 全面适配 sing-box
2025-12-31 13:40:58 +08:00
小小小猫仔
504d7b39d4 ShellCrash_RS_Full_BanAds 全面适配 sing-box
ShellCrash_RS_Full_BanAds 全面适配 sing-box
2025-12-31 13:39:21 +08:00
juewuy
3bcf432873 Merge pull request #1062 from Maozai-Teng/dev
优化规则集下载
2025-12-31 13:37:44 +08:00
小小小猫仔
10bdd0fd53 优化规则集下载
优化规则集下载
2025-12-31 13:34:57 +08:00
juewuy
3b17d3070b Merge pull request #1061 from DustinWin/dev
优化 sing-box 规则集文件下载体验
2025-12-31 12:57:18 +08:00
DustinWin
e225ef1b3a 优化 sing-box 规则集文件下载体验 2025-12-31 12:44:30 +08:00
nested-universe
258267436b Restore source script operation logic 2025-12-31 12:33:05 +08:00
nested-universe
c7d5506b38 Improve upgrade function
Replace self-invoking functions with a while-true loop.

Change the menu return logic.
2025-12-31 12:06:11 +08:00
juewuy
175d6a2b65 Merge pull request #1059 from DustinWin/dev
~回退去广告规则相关修改,优化直连出口描述
2025-12-31 11:23:22 +08:00
DustinWin
a5dd89ec56 ~回退去广告规则相关修改,优化直连出口描述 2025-12-31 11:18:40 +08:00
juewuy
31b1201dfe ~回退去广告规则相关修改,优化直连出口描述 2025-12-31 10:52:47 +08:00
juewuy
bbfcdbdd65 ~修复自动编译报错 2025-12-31 10:32:49 +08:00
juewuy
9cb99fbe76 ~修改docker自动build条件,改为必须version文件变化才会触发 2025-12-31 10:10:41 +08:00
juewuy
63c34ea549 ~1.9.3alpha5.1打包
~修复部分调用工具或者界面报错的bug
~修复bot_tg胡乱推送消息以及可能多进程同时存在的bug
~修复nftables启动报错
~修复Tailscale无法正确启用域名嗅探以及dns劫持失效的bug
2025-12-29 10:24:45 +08:00
juewuy
86aa280c94 ~修复自动编译singboxr内核版本弄混了的问题 2025-12-29 09:58:07 +08:00
juewuy
41c3e5d4cc Merge branch 'master' into dev
# Conflicts:
#	scripts/webget.sh
2025-12-28 21:20:35 +08:00
juewuy
86c518d788 ~1.9.3alpha5打包 2025-12-28 21:15:59 +08:00
juewuy
c9cb6d41ac ~优化dns菜单,移除fake-ip模式,并将部分原进阶选项移动至dns主菜单
~优化tg-bot绑定流程,增加循环检测对话ID机制
~优化tg-bot启动逻辑,现在不会随着内核服务重启而重启进而导致死循环
~优化公网防火墙功能,增加一键清空功能,增加vmess和ss端口的额外显示
~优化vmess和ss的界面逻辑,增加vmess一键生成时的混淆host输入
~修复因为未选择ss加密类型而导致启动失败的bug
~修复小米/网件镜像化设备重启后服务丢失的bug
~修复因为切换vmess和ss端口导致公网防火墙启动报错的bug
~修复6-5设置定时任务报错的bug
2025-12-28 21:15:34 +08:00
juewuy
ad19f96138 增加kk-rays.com域名 2025-12-28 19:13:42 +08:00
juewuy
a13954fd61 Merge pull request #1054 from Maozai-Teng/dev
上线ShellCrash_RS_Full_BanAds.yaml
2025-12-28 08:51:30 +08:00
小小小猫仔
bfd11543bd 上线ShellCrash_RS_Full_BanAds.yaml
上线ShellCrash_RS_Full_BanAds.yaml
2025-12-28 08:50:42 +08:00
juewuy
010ec5d24e ~修复启用tg_bot服务后,关闭服务偶尔会卡住的bug 2025-12-27 22:24:51 +08:00
juewuy
ac6ccc7d0c ~修复nftables启动报错 2025-12-27 22:12:02 +08:00
juewuy
9b4618a37a ~1.9.3alpha4打包 2025-12-27 21:58:05 +08:00
juewuy
daa600dbea ~优化tg-bot启动流程,兼容更多设备
~优化nftables启动流程,优化启用cn绕过时的运行效率和数据显示
~修复tg机器人守护进程没有生效的bug
~修复tg机器人总是绑定失败的bug
~修复9-8功能找不到文件的bug
~修复停止服务时的报错
~修复启动时自动下载缺失数据库时的意外报错
~修复nftables启用了本机代理后局域网代理出错的bug
2025-12-27 21:57:24 +08:00
juewuy
ecf99aac39 ~1.9.3alpha3打包 2025-12-27 17:33:24 +08:00
juewuy
1a273ec274 ~重写保守模式启动函数,现在启动停止不会有额外kill命令报错,并且增加了对tg_bot脚本的启动支持
~新增tg_bot脚本的定时任务守护进程功能
~新增公网防火墙禁用时的警告确认功能
~优化小米路由自启脚本,现在自启脚本单独存放为/data/shellcrash_init.sh,且在卸载脚本时会保留改脚本并保留软固化功能
~优化小米自动清理功能,适配更多设备
~修复本地自解压安装时脚本报错bug
~修复小米等设备无法使用tg_bot控制机器人的问题
2025-12-27 17:32:40 +08:00
juewuy
8c7a5bec47 ~1.9.3alpha2.2打包
~修复更新失败的相关bug
~修复systemd启动失败的bug
2025-12-27 09:58:34 +08:00
juewuy
3dbb33f3a7 ~1.9.3alpha2.1打包
~修复新手引导和自启网络检测的相关bug
2025-12-27 09:11:45 +08:00
juewuy
302e828c94 ~1.9.3alpha2打包 2025-12-26 20:53:10 +08:00
juewuy
b792fc54f3 ~修复报错 2025-12-26 20:52:00 +08:00
juewuy
ab774251b0 ~大幅度优化tg_bot控制脚本 2025-12-26 20:42:13 +08:00
juewuy
91686c82da Merge branch 'master' into dev
# Conflicts:
#	scripts/start.sh
2025-12-26 17:46:33 +08:00
juewuy
1f477a5934 ~继续优化代码
~bot_tg.sh施工中
2025-12-26 17:35:45 +08:00
juewuy
0b3beca6a9 Merge branch 'master' into dev
# Conflicts:
#	scripts/start.sh
2025-12-26 10:27:06 +08:00
juewuy
3153ea1acc ~修复iptables公网防火墙的bug 2025-12-25 22:48:09 +08:00
juewuy
d1c9bccfbe ~脚本拆分后bug修复 2025-12-25 21:49:05 +08:00
juewuy
a1835b7113 ~脚本拆分后bug修复 2025-12-25 21:07:21 +08:00
juewuy
17705d67f1 Merge branch 'dev' of https://github.com/juewuy/ShellCrash into dev 2025-12-25 15:51:13 +08:00
juewuy
647b52e016 ~脚本进行大量拆分和优化 2025-12-25 15:50:58 +08:00
juewuy
c415036f3f Merge pull request #1051 from Maozai-Teng/dev
优化文本
2025-12-25 11:04:33 +08:00
小小小猫仔
ed2b359ce8 Merge branch 'juewuy:dev' into dev 2025-12-25 10:30:57 +08:00
小小小猫仔
3fd86538fd 优化文本
优化文本
2025-12-25 10:30:49 +08:00
juewuy
e62f485df4 ~继续拆分脚本 2025-12-24 11:09:28 +08:00
juewuy
1a4330cb86 ~移动文件 2025-12-24 10:05:01 +08:00
juewuy
6d64d3b2b3 ~移动文件 2025-12-24 10:03:30 +08:00
juewuy
bf2e730035 Merge pull request #1050 from Maozai-Teng/dev
优化一些细节~
2025-12-23 20:07:26 +08:00
小小小猫仔
f1fcd58e34 优化一些细节~
优化一些细节~
2025-12-23 16:56:21 +08:00
juewuy
6338110530 ~拆分工具 2025-12-22 21:23:50 +08:00
juewuy
70eb022859 Merge branch 'master' into dev
# Conflicts:
#	scripts/menu.sh
2025-12-22 20:45:15 +08:00
juewuy
c4c1866178 Merge branch 'dev' of https://github.com/juewuy/ShellCrash into dev 2025-12-22 19:30:44 +08:00
juewuy
18a829c101 ~继续拆分脚本
~重写公网防火墙功能
2025-12-22 19:30:29 +08:00
juewuy
d01adefd14 Merge pull request #1049 from Maozai-Teng/dev
重新排序优化rules,整理proxy-groups
2025-12-22 15:48:17 +08:00
小小小猫仔
e0f2c20588 重新排序优化rules,整理proxy-groups
重新排序优化rules,整理proxy-groups
2025-12-22 14:45:47 +08:00
juewuy
ada0ec70ea Merge branch 'master' into dev 2025-12-22 10:10:29 +08:00
juewuy
bf55553d63 ~拆分脚本,大幅度优化结构 2025-12-21 22:11:05 +08:00
juewuy
1ed156f724 Merge branch 'gateway' into dev 2025-12-21 18:09:51 +08:00
juewuy
871ca7eb8a ~优化菜单结构 2025-12-21 11:04:14 +08:00
juewuy
ac8f225c4f ~拆分组件 2025-12-20 20:31:06 +08:00
juewuy
9a2d98a6b8 ~继续优化 2025-12-20 20:30:50 +08:00
juewuy
51f5795731 ~添加ss和vmess入站支持 2025-12-20 12:54:42 +08:00
juewuy
8d20c90900 Merge branch 'dev' into gateway 2025-12-20 11:35:27 +08:00
juewuy
455b97c9b5 Merge branch 'dev' into gateway 2025-12-19 22:57:57 +08:00
juewuy
e1e8aba4ee 已添加 scripts/libs/check_port.sh 2025-12-19 22:21:32 +08:00
juewuy
5ce80fdf3b 添加vmess入站 2025-12-19 22:18:40 +08:00
juewuy
972ddbafcc Merge branch 'dev' into gateway 2025-12-19 20:05:38 +08:00
juewuy
c42bd05603 Merge branch 'dev' into gateway
# Conflicts:
#	scripts/start.sh
2025-12-19 19:11:10 +08:00
juewuy
417c15db60 重命名 scripts/menus/bot_tg.sh (从 scripts/components/bot_tg.sh)
重命名        scripts/menus/ddns_op.sh (从 scripts/components/ddns_op.sh)
重命名        scripts/menus/endpoints.sh (从 scripts/components/endpoints.sh)
重命名        scripts/menus/gateway.sh (从 scripts/components/gateway.sh)
2025-12-18 21:53:49 +08:00
juewuy
2f6172f7b5 Merge branch 'dev' into gateway 2025-12-18 21:45:17 +08:00
juewuy
0aff2018ff Merge branch 'dev' into gateway
# Conflicts:
#	scripts/start.sh
2025-12-15 21:35:44 +08:00
juewuy
9c8e9d65a5 Merge branch 'dev' into gateway 2025-12-15 14:02:36 +08:00
juewuy
951d93a055 已修改 scripts/components/endpoints.sh
已修改        scripts/components/gateway.sh
已修改        scripts/start.sh
2025-12-14 22:14:25 +08:00
juewuy
9751ce9271 Merge branch 'dev' into gateway 2025-12-14 19:28:03 +08:00
juewuy
e204bf7bf5 Merge branch 'dev' into gateway
# Conflicts:
#	scripts/start.sh
2025-12-14 19:03:18 +08:00
juewuy
602d454421 已添加 scripts/components/bot_tg.sh
已添加        scripts/components/ddns_op.sh
已修改        scripts/components/gateway.sh
2025-12-14 08:50:18 +08:00
juewuy
3c302d6e1f ~优化 2025-12-12 22:13:12 +08:00
juewuy
6ff3cc4f3e Merge branch 'dev' into gateway 2025-12-12 21:55:48 +08:00
juewuy
7bdd32459f ~增加tailscale设置 2025-12-12 21:46:14 +08:00
juewuy
c387fd4e76 Merge branch 'dev' into gateway 2025-12-12 19:17:36 +08:00
juewuy
45abeaf1db 已添加 scripts/components/gateway.sh 2025-12-12 11:38:31 +08:00
128 changed files with 14273 additions and 8666 deletions

View File

@@ -2,47 +2,35 @@ name: core_auto_update
on:
schedule:
- cron: 0 18 * * *
- cron: 0 18 */3 * *
workflow_dispatch:
jobs:
check_version:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
with:
repository: reF1nd/sing-box
ref: reF1nd-dev
fetch-depth: 0
- name: Check version
run: |
git remote add sekai https://github.com/SagerNet/sing-box.git
git fetch --tags sekai
version_new=$(CGO_ENABLED=0 go run ./cmd/internal/read_tag)
version_old=$(curl -sSl https://github.com/juewuy/ShellCrash/releases/download/singbox_core_reF1nd/version)
if [ "$version_old" != "$version_new" ];then
echo a=$version_old >> $GITHUB_ENV
echo b=$version_new >> $GITHUB_ENV
else
echo "未检查到版本更新,已退出!"
exit 1
fi
auto_update_singboxp_with_wg:
needs: check_version
if: ${{ success() }}
auto_update_singboxr_dev:
permissions: write-all
uses: juewuy/ShellCrash/.github/workflows/update_singbox_core.yaml@dev
with:
tag1: reF1nd/sing-box
tag2: reF1nd-dev
tag3: singbox_core_reF1nd
tag5: with_quic,with_dhcp,with_wireguard,with_tailscale,with_shadowsocksr,with_utls,with_clash_api,with_gvisor
tag4: singboxr
tag5: with_gvisor,with_quic,with_dhcp,with_wireguard,with_utls,with_shadowsocksr,with_acme,with_clash_api,with_tailscale
tag6: gz
secrets: inherit
auto_update_meta_alpha:
permissions: write-all
needs: auto_update_singboxr_dev
uses: juewuy/ShellCrash/.github/workflows/update_meta_core.yaml@dev
with:
tag1: MetaCubeX/mihomo
tag2: Alpha
tag4: meta
tag5: with_gvisor
tag6: gz
secrets: inherit
cleanup:
needs: check_version
runs-on: ubuntu-latest
steps:
- name: cleanup

89
.github/workflows/core_easy_update.yaml vendored Normal file
View File

@@ -0,0 +1,89 @@
name: core_easy_update
on:
workflow_dispatch:
inputs:
tag1:
description: 'meta or singbox or singboxr'
required: true
type: string
jobs:
get_version:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.get_version.outputs.version }}
steps:
- id: get_version
run: |
[ "${{ inputs.tag1 }}" = meta ] && repo="MetaCubeX/mihomo"
[ "${{ inputs.tag1 }}" = singbox ] && repo="SagerNet/sing-box"
[ "${{ inputs.tag1 }}" = singboxr ] && repo="SagerNet/sing-box"
latest_tag=$(curl -s "https://api.github.com/repos/$repo/releases/latest" | jq -r .tag_name)
echo "version=$latest_tag" >> $GITHUB_OUTPUT
update_meta_upx:
if: github.event.inputs.tag1 == 'meta'
needs: get_version
permissions: write-all
uses: juewuy/ShellCrash/.github/workflows/update_meta_core.yaml@dev
with:
tag1: MetaCubeX/mihomo
tag2: ${{ needs.get_version.outputs.version }}
tag4: meta
tag5: ""
tag6: upx
secrets: inherit
update_meta_tar:
if: github.event.inputs.tag1 == 'meta'
needs: [get_version, update_meta_upx]
permissions: write-all
uses: juewuy/ShellCrash/.github/workflows/update_meta_core.yaml@dev
with:
tag1: MetaCubeX/mihomo
tag2: ${{ needs.get_version.outputs.version }}
tag4: meta
tag5: ""
tag6: tar.gz
secrets: inherit
update_singboxr_upx:
if: github.event.inputs.tag1 == 'singboxr'
needs: get_version
permissions: write-all
uses: juewuy/ShellCrash/.github/workflows/update_singbox_core.yaml@dev
with:
tag1: reF1nd/sing-box
tag2: ${{ needs.get_version.outputs.version }}
tag4: singboxr
tag5: with_quic,with_utls,with_clash_api
tag6: upx
secrets: inherit
update_singboxr_tar:
if: github.event.inputs.tag1 == 'singboxr'
needs: [get_version, update_singboxr_upx]
permissions: write-all
uses: juewuy/ShellCrash/.github/workflows/update_singbox_core.yaml@dev
with:
tag1: reF1nd/sing-box
tag2: ${{ needs.get_version.outputs.version }}
tag4: singboxr
tag5: with_gvisor,with_quic,with_wireguard,with_utls,with_clash_api,with_tailscale
tag6: tar.gz
secrets: inherit
update_singbox_upx:
if: github.event.inputs.tag1 == 'singbox'
needs: get_version
permissions: write-all
uses: juewuy/ShellCrash/.github/workflows/update_singbox_core.yaml@dev
with:
tag1: SagerNet/sing-box
tag2: ${{ needs.get_version.outputs.version }}
tag4: singbox
tag5: with_quic,with_utls,with_clash_api
tag6: upx
secrets: inherit

View File

@@ -23,6 +23,31 @@ on:
description: 'build tags'
required: false
type: string
tag6:
description: 'ziptype(tar.gz|upx|gz)'
required: true
type: string
workflow_call:
inputs:
tag1:
required: true
type: string
tag2:
required: true
type: string
tag3:
required: false
type: string
tag4:
required: false
type: string
tag5:
required: false
type: string
tag6:
required: true
type: string
jobs:
go:
@@ -39,8 +64,8 @@ jobs:
runs-on: ubuntu-latest
needs: go
env:
REPO: ${{ github.event.inputs.tag1 }}
TAGS: ${{ github.event.inputs.tag5 }}
REPO: ${{ inputs.tag1 }}
TAGS: ${{ inputs.tag5 }}
outputs:
version: ${{steps.meta.outputs.version}}
tags: ${{steps.meta.outputs.tags}}
@@ -49,7 +74,8 @@ jobs:
- name: get meta version
id: meta
run: |
version=${{ github.event.inputs.tag2 }}
version=${{ inputs.tag2 }}
[ "$version" = Alpha ] && version="Alpha-$(date +"%Y%m%d")"
echo version=$version >> $GITHUB_OUTPUT
if [ -z "$TAGS" ];then
echo tags='' >> $GITHUB_OUTPUT
@@ -111,30 +137,14 @@ jobs:
- name: Checkout meta
uses: actions/checkout@v5
with:
repository: ${{ github.event.inputs.tag1 }}
ref: ${{ github.event.inputs.tag2 }}
repository: ${{ inputs.tag1 }}
ref: ${{ inputs.tag2 }}
fetch-depth: 1
- name: Setup Go
uses: actions/setup-go@v6
with:
go-version: ${{needs.go.outputs.version}}
- name: Set variables
run: |
VERSION="${GITHUB_REF_NAME,,}-$(git rev-parse --short HEAD)"
VERSION="${VERSION//\//-}"
PackageVersion="$(curl -s "https://api.github.com/repos/MetaCubeX/mihomo/releases/latest" | jq -r '.tag_name' | sed 's/v//g' | awk -F '.' '{$NF = $NF + 1; print}' OFS='.').${VERSION/-/.}"
if [ -n "${{ github.event.inputs.version }}" ]; then
VERSION=${{ github.event.inputs.version }}
PackageVersion="${VERSION#v}"
fi
echo "VERSION=${VERSION}" >> $GITHUB_ENV
echo "PackageVersion=${PackageVersion}" >> $GITHUB_ENV
echo "BUILDTIME=$(date)" >> $GITHUB_ENV
echo "CGO_ENABLED=0" >> $GITHUB_ENV
echo "BUILDTAG=-extldflags --static" >> $GITHUB_ENV
echo "GOTOOLCHAIN=local" >> $GITHUB_ENV
- name: Update CA
run: |
@@ -145,13 +155,14 @@ jobs:
- name: build core
id: build
run: |
go env
go build -v -tags "${TAGS}" -o meta -trimpath -ldflags "${BUILDTAG} -X 'github.com/metacubex/mihomo/constant.Version=${VERSION}' -X 'github.com/metacubex/mihomo/constant.BuildTime=${BUILDTIME}' -w -s -buildid="
go build -v -tags "${TAGS}" -o meta -trimpath -ldflags "-extldflags --static -X 'github.com/metacubex/mihomo/constant.Version=${VERSION}' -X 'github.com/metacubex/mihomo/constant.BuildTime=$(date)' -w -s -buildid="
- name: Upload file to workspace
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.name }}
path: meta
overwrite: true
push_to_git:
needs:
@@ -159,8 +170,9 @@ jobs:
- meta
runs-on: ubuntu-latest
env:
RELEASE: ${{ github.event.inputs.tag3 }}
PUSHDIR: ${{ github.event.inputs.tag4 }}
RELEASE: ${{ inputs.tag3 }}
PUSHDIR: ${{ inputs.tag4 }}
ZIPTYPE: ${{ inputs.tag6 }}
VERSION: ${{needs.meta.outputs.version}}
steps:
- name: Checkout ShellCrash
@@ -174,7 +186,33 @@ jobs:
with:
path: ./tmp
- name: Zip core by upx
if: env.ZIPTYPE == 'upx'
run: |
for upxv in 3.94 3.96 5.1.0;do
wget https://github.com/upx/upx/releases/download/v$upxv/upx-$upxv-amd64_linux.tar.xz
tar xf upx-$upxv-amd64_linux.tar.xz
done
for arch in amd64 armv5 armv7 arm64 386 mips-softfloat mipsle-hardfloat mipsle-softfloat;do
[ ! -f ./tmp/linux-${arch}/meta ] && continue
mv -f ./tmp/linux-${arch}/meta ./tmp/clash-linux-${arch}.upx
chmod +x ./tmp/clash-linux-${arch}.upx
case "${arch}" in
armv5|mips* )
./upx-3.94-amd64_linux/upx --no-lzma ./tmp/clash-linux-${arch}.upx
;;
armv7|386)
./upx-3.96-amd64_linux/upx --no-lzma ./tmp/clash-linux-${arch}.upx
;;
*)
./upx-5.1.0-amd64_linux/upx ./tmp/clash-linux-${arch}.upx
;;
esac
done
rm -rf upx-*
- name: Zip core by tar
if: env.ZIPTYPE == 'tar.gz'
run: |
for arch in amd64 armv5 armv7 arm64 386 mips-softfloat mipsle-hardfloat mipsle-softfloat;do
[ ! -f ./tmp/linux-${arch}/meta ] && continue
@@ -183,15 +221,24 @@ jobs:
tar --no-same-owner -zcvf ./tmp/clash-linux-${arch}.tar.gz -C ./tmp CrashCore
done
- name: Zip core by gz
if: env.ZIPTYPE == 'gz'
run: |
for arch in amd64 armv5 armv7 arm64 386 mips-softfloat mipsle-hardfloat mipsle-softfloat;do
[ ! -f ./tmp/linux-${arch}/meta ] && continue
mv -f ./tmp/linux-${arch}/meta ./tmp/clash-linux-${arch}
chmod +x ./tmp/clash-linux-${arch}
gzip ./tmp/clash-linux-${arch}
done
- name: Commit and push
if: ${{ env.PUSHDIR != '' }}
run: |
crashcore='meta'
[ "${{ inputs.tag1 }}" = MetaCubeX/mihomo ] && crashcore='meta'
mkdir -p ./bin/${crashcore}
rm -fr ./bin/${crashcore}/*
mv -f ./tmp/clash-linux-*.tar.gz ./bin/${crashcore}/
mv -f ./tmp/clash-linux-* ./bin/${crashcore}/
rm -fr ./tmp
sed -i "s/${crashcore}_v=.*/${crashcore}_v=${VERSION}/" ./bin/version
[ "${{ inputs.tag6 }}" = tar.gz ] && sed -i "s/${crashcore}_v=.*/${crashcore}_v=${VERSION}/" ./bin/version
git config --global user.email "github-actions[bot]@users.noreply.github.com" && git config --global user.name "github-actions[bot]"
git add . && git commit -m "更新${crashcore}内核至${VERSION}" || exit 0
git push
@@ -206,9 +253,9 @@ jobs:
if: ${{ env.RELEASE != '' && env.PUSHDIR == '' }}
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ github.event.inputs.tag3 }}
name: ${{ github.event.inputs.tag3 }}
body: "The ${{env.VERSION}} version of ${{ github.event.inputs.tag1 }} \n这是${{ github.event.inputs.tag1 }}的${{env.VERSION}}版本内核文件\nhttps://github.com/${{ github.event.inputs.tag1 }}/releases \nOnly support for ShellCrash\n仅适配ShellCrash项目"
tag_name: ${{ inputs.tag3 }}
name: ${{ inputs.tag3 }}
body: "The ${{env.VERSION}} version of ${{ inputs.tag1 }} \n这是${{ inputs.tag1 }}的${{env.VERSION}}版本内核文件\nhttps://github.com/${{ inputs.tag1 }}/releases \nOnly support for ShellCrash\n仅适配ShellCrash项目"
draft: false
prerelease: true
files: |
@@ -219,3 +266,6 @@ jobs:
with:
retain_days: 1
keep_minimum_runs: 2

View File

@@ -23,6 +23,11 @@ on:
description: 'build tags'
required: false
type: string
tag6:
description: 'ziptype(tar.gz|upx|gz)'
required: true
type: string
workflow_call:
inputs:
tag1:
@@ -40,6 +45,9 @@ on:
tag5:
required: false
type: string
tag6:
required: true
type: string
jobs:
go:
@@ -80,6 +88,7 @@ jobs:
git fetch --tags sekai
version=$(CGO_ENABLED=0 go run ./cmd/internal/read_tag)
[ -z "$version" ] && version=${{ inputs.tag2 }}
version=$(echo ${version%-*})
echo version=$version >> $GITHUB_OUTPUT
if [ -z "$TAGS" ];then
if [ "$REPO" = 'SagerNet/sing-box' ];then
@@ -117,11 +126,11 @@ jobs:
goos: linux
goarch: mips
gomips: softfloat
- name: linux-mipsel-softfloat
- name: linux-mipsle-softfloat
goos: linux
goarch: mipsle
gomips: softfloat
- name: linux-mipsel-hardfloat
- name: linux-mipsle-hardfloat
goos: linux
goarch: mipsle
gomips: hardfloat
@@ -171,6 +180,7 @@ jobs:
with:
name: ${{ matrix.name }}
path: sing-box
overwrite: true
push_to_git:
needs:
@@ -180,6 +190,7 @@ jobs:
env:
RELEASE: ${{ inputs.tag3 }}
PUSHDIR: ${{ inputs.tag4 }}
ZIPTYPE: ${{ inputs.tag6 }}
VERSION: ${{needs.sing-box.outputs.version}}
steps:
- name: Checkout ShellCrash
@@ -194,18 +205,51 @@ jobs:
with:
path: ./tmp
- name: Zip core by upx
if: env.ZIPTYPE == 'upx'
run: |
for upxv in 3.94 3.96 5.1.0;do
wget https://github.com/upx/upx/releases/download/v$upxv/upx-$upxv-amd64_linux.tar.xz
tar xf upx-$upxv-amd64_linux.tar.xz
done
for arch in amd64 armv5 armv7 arm64 386 mips-softfloat mipsle-hardfloat mipsle-softfloat;do
[ ! -f ./tmp/linux-${arch}/sing-box ] && continue
mv -f ./tmp/linux-${arch}/sing-box ./tmp/singbox-linux-${arch}.upx
chmod +x ./tmp/singbox-linux-${arch}.upx
case "${arch}" in
armv5|mips* )
./upx-3.94-amd64_linux/upx --no-lzma ./tmp/singbox-linux-${arch}.upx
;;
armv7|386)
./upx-3.96-amd64_linux/upx --no-lzma ./tmp/singbox-linux-${arch}.upx
;;
*)
./upx-5.1.0-amd64_linux/upx ./tmp/singbox-linux-${arch}.upx
;;
esac
done
rm -rf upx-*
- name: Zip core by tar
run: |
for arch in amd64 armv5 armv7 arm64 386 mips-softfloat mipsel-hardfloat mipsel-softfloat;do
if: env.ZIPTYPE == 'tar.gz'
run: |
for arch in amd64 armv5 armv7 arm64 386 mips-softfloat mipsle-hardfloat mipsle-softfloat;do
[ ! -f ./tmp/linux-${arch}/sing-box ] && continue
mv -f ./tmp/linux-${arch}/sing-box ./tmp/CrashCore
chmod +x ./tmp/CrashCore
tar --no-same-owner -zcvf ./tmp/singbox-linux-${arch}.tar.gz -C ./tmp CrashCore
done
mv -f ./tmp/singbox-linux-mipsel-hardfloat.tar.gz ./tmp/singbox-linux-mipsle-hardfloat.tar.gz
mv -f ./tmp/singbox-linux-mipsel-softfloat.tar.gz ./tmp/singbox-linux-mipsle-softfloat.tar.gz
echo ${VERSION} > ./tmp/version
- name: Zip core by gz
if: env.ZIPTYPE == 'gz'
run: |
for arch in amd64 armv5 armv7 arm64 386 mips-softfloat mipsle-hardfloat mipsle-softfloat;do
[ ! -f ./tmp/linux-${arch}/sing-box ] && continue
mv -f ./tmp/linux-${arch}/sing-box ./tmp/singbox-linux-${arch}
chmod +x ./tmp/singbox-linux-${arch}
gzip ./tmp/singbox-linux-${arch}
done
- name: Commit and push
if: ${{ env.PUSHDIR != '' }}
run: |
@@ -213,10 +257,9 @@ jobs:
[ "${{ inputs.tag1 }}" = PuerNya/sing-box ] && crashcore='singboxp'
[ "${{ inputs.tag1 }}" = reF1nd/sing-box ] && crashcore='singboxr'
mkdir -p ./bin/${crashcore}
rm -fr ./bin/${crashcore}/*
mv -f ./tmp/singbox-linux-*.tar.gz ./bin/${crashcore}/
mv -f ./tmp/singbox-linux-* ./bin/${crashcore}/
rm -fr ./tmp
sed -i "s/${crashcore}_v=.*/${crashcore}_v=${VERSION}/" ./bin/version
[ "${{ inputs.tag6 }}" = tar.gz ] && sed -i "s/${crashcore}_v=.*/${crashcore}_v=${VERSION}/" ./bin/version
git config --global user.email "github-actions[bot]@users.noreply.github.com" && git config --global user.name "github-actions[bot]"
git add . && git commit -m "更新${crashcore}内核至${VERSION}" || exit 0
git push

176
README.md
View File

@@ -1,24 +1,178 @@
<h1 align="center">
<br>ShellCrash<br>
</h1>
<p align="center">
<h1 align="center">ShellCrash</h1>
<p align="center">
<a target="_blank" href="https://github.com/MetaCubeX/mihomo/releases">
<img src="https://img.shields.io/github/release/MetaCubeX/mihomo.svg?style=flat-square&label=Core">
</a>
<a target="_blank" href="https://github.com/juewuy/ShellCrash/releases">
<img src="https://img.shields.io/github/release/juewuy/ShellCrash.svg?style=flat-square&label=ShellCrash&colorB=green">
</a>
</p>
[中文](README_CN.md) | English
<p align="center">
<strong>A powerful script tool for the convenient deployment and management of mihomo/sing-box kernels in Shell environments.</strong>
</p>
## Function introduction:
<p align="center">
<a href="README_CN.md">简体中文</a> | English
</p>
~Convenient use in Shell environment through management script [Crash](https://github.com/Dreamacro/Crash)<br>~Support management of [Crash functions](https://lancellc.gitbook.io/Crash)<br>~Support online import [Crash](https://github.com/Dreamacro/Crash) supports sharing, subscription and configuration links<br>~Support configuration timing tasks, support configuration file timing updates<br>~Support online installation and Use local web panel to manage built-in rules<br>~Support routing mode, native mode and other mode switching<br>~Support online update<br>
---
## Equipment support:
## :rocket: Core Features
~Support various router devices based on OpenWrt or secondary custom development using OpenWrt<br>~Support various devices running standard Linux systems (such as Debian/CenOS/Armbian, etc.)<br>~Compatible with Padavan firmware (conservative mode), Pandora firmware<br>~Compatible with various types of devices customized and developed using the Linux kernel<br>——————————<br>~For more device support, please submit an issue or go to the TG group for feedback (the device name and the device core information returned by running uname -a must be provided)<br>
- **Multi-Kernel Support**: Easily manage and switch between **mihomo** and **sing-box** kernels directly within the Shell environment.
- **Flexible Configuration Management**: Supports online import of subscription links and configuration files to simplify the setup process.
- **Automated Tasks**: Configure scheduled tasks for automatic updates of configuration files and rules.
- **Graphical Dashboard**: Support for online installation and use of local Web Dashboards to intuitively manage built-in rules and traffic.
- **Multiple Operation Modes**: Supports switching between various traffic forwarding modes, including Router mode and Local mode.
- **One-Click Maintenance**: Built-in online update functionality to keep the script and features up to date.
## :computer: Device Support
ShellCrash is designed to be compatible with the vast majority of network devices based on the Linux kernel:
* **Router Devices**: Supports various firmwares based on OpenWrt or its derivatives (e.g., Xiaomi, Netgear etc.).
* **Linux Servers**: Supports devices running standard Linux/GNU distributions (e.g., Debian, CentOS, Armbian, Ubuntu, etc.).
* **Third-Party Firmware**: Compatible with Padavan (Conservative Mode), Pandora, and ASUS/Merlin firmware.
* **Other Devices**: Compatible with other devices based on Linux/GNU or Linux/busybox.
* **Docker**Compatible with Docker environments (e.g., Synology, PVE, etc.).
> For additional device support, please submit an [Issue](https://github.com/juewuy/ShellCrash/issues) or provide feedback in the [Telegram Group](https://t.me/ShellClash) (please include the device model and the output of the `uname -a` command).
---
## :hammer_and_wrench: Installation Guide
> [!TIP]
> If you encounter connection failures or SSL-related issues, please try switching to an alternative installation mirror.
### Prerequisites
1. Ensure the device has **SSH** enabled and **Root privileges** obtained (Linux systems with a GUI can use the terminal directly).
2. Connect to the device using an SSH tool (such as PuTTY, JuiceSSH, or the system's built-in terminal).
### :penguin: Standard Linux Device Installation
> [!IMPORTANT]
> Please perform the installation as the root user.
> Install via wget (jsDelivr CDN source)
```sh
export url='https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@dev' \
&& wget -q --no-check-certificate -O /tmp/install.sh $url/install_en.sh \
&& bash /tmp/install.sh \
&& . /etc/profile &> /dev/null
```
> Or install via curl (Author's private source)
```sh
export url='https://gh.jwsc.eu.org/dev' && bash -c "$(curl -kfsSl $url/install_en.sh)" && . /etc/profile &> /dev/null
```
### :satellite: Router Device Installation
**Installation via `curl`:**
> GitHub Source (Recommended for overseas environments or environments with proxy access)
```sh
export url='https://raw.githubusercontent.com/juewuy/ShellCrash/dev' \
&& sh -c "$(curl -kfsSl $url/install_en.sh)" \
&& . /etc/profile &> /dev/null
```
> Or jsDelivr CDN source
```sh
export url='https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@dev' \
&& sh -c "$(curl -kfsSl $url/install_en.sh)" \
&& . /etc/profile &> /dev/null
```
> Or Author's private source
```sh
export url='https://gh.jwsc.eu.org/dev' && sh -c "$(curl -kfsSl $url/install_en.sh)" && . /etc/profile &> /dev/null
```
**Installation via `wget`:**
> GitHub Source (Recommended for overseas environments or environments with proxy access)
```sh
export url='https://raw.githubusercontent.com/juewuy/ShellCrash/dev' \
&& wget -q --no-check-certificate -O /tmp/install.sh $url/install_en.sh \
&& sh /tmp/install.sh \
&& . /etc/profile &> /dev/null
```
> Or jsDelivr CDN source
```sh
export url='https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@dev' \
&& wget -q --no-check-certificate -O /tmp/install.sh $url/install_en.sh \
&& sh /tmp/install.sh \
&& . /etc/profile &> /dev/null
```
### :pager: Installation for Legacy Devices with Older `wget` Versions
> Author's private HTTP beta source
```sh
export url='http://t.jwsc.eu.org' \
&& wget -q -O /tmp/install.sh $url/install_en.sh \
&& sh /tmp/install.sh \
&& . /etc/profile &> /dev/null
```
### :cloud: Virtual Machines
- **Alpine Linux VM**: It is highly recommended to use an Alpine image for optimal compatibility.
```sh
# Install necessary dependencies
apk add --no-cache wget openrc ca-certificates tzdata nftables iproute2 dcron
# Execute installation command
export url='https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@dev' \
&& wget -q --no-check-certificate -O /tmp/install.sh $url/install_en.sh \
&& sh /tmp/install.sh \
&& . /etc/profile &> /dev/null
```
### :whale: Docker
Please visit the official Docker image:
- [ShellCrash on Docker Hub](https://hub.docker.com/r/juewuy/shellcrash)
### :package: Local Installation
If online installation is not possible, please follow the guide for local installation:
- [Local ShellCrash Installation Tutorial | Juewuy's Blog](https://juewuy.github.io/bdaz)
---
## :book: Usage Instructions
After installation, enter the following commands in the terminal to launch the management interface:
```shell
crash # Launch the interactive script menu
crash -h # View the list of command help
```
### Running Dependencies
| Component | Necessity | Description |
| :--- | :--- | :--- |
| curl / wget | Mandatory | Required for node saving, online installation, and update operations. |
| iptables / nftables | Critical | Without these, the script can only run in Pure Mode. |
| crontab | Low | Required for scheduled tasks; otherwise, they will not function. |
| net-tools | Very Low | Used for automatic port occupancy detection. |
| ubus / iproute-doc | Very Low | Used for automatically obtaining the local Host address. |
---
## :link: Related Links
- FAQ: [Juewuy's Blog](https://juewuy.github.io/chang-jian-wen-ti/)
- Changelog: [Release History](https://github.com/juewuy/ShellCrash/releases)
- Discussion: [Telegram Group](https://t.me/ShellClash)
## :scroll: License
This project is licensed under the [GNU General Public License v3.0](LICENSE.txt).

View File

@@ -1,10 +1,7 @@
<h1 align="center">
<br>ShellCrash<br>
</h1>
<h1 align="center">ShellCrash</h1>
<p align="center">
<a target="_blank" href="https://github.com/MetaCubeX/mihomo/releases">
<p align="center">
<a target="_blank" href="https://github.com/MetaCubeX/mihomo/releases">
<img src="https://img.shields.io/github/release/MetaCubeX/mihomo.svg?style=flat-square&label=Core">
</a>
<a target="_blank" href="https://github.com/juewuy/ShellCrash/releases">
@@ -12,147 +9,184 @@
</a>
</p>
中文 | [English](README.md)
<p align="center">
<strong>一款在 Shell 环境下便捷部署与管理 mihomo/sing-box 内核的脚本工具</strong>
</p>
功能简介:
--
<p align="center">
简体中文 | <a href="README.md">English</a>
</p>
~通过管理脚本在Shell环境下便捷使用Mihomo/Singbox内核<br>
~支持在Shell环境下管理<br>
~支持在线导入订阅及配置链接<br>
~支持配置定时任务,支持配置文件定时更新<br>
~支持在线安装及使用本地网页面板管理内置规则<br>
~支持路由模式、本机模式等多种模式切换<br>
~支持在线更新<br>
---
设备支持:
--
## :rocket: 核心特性
~支持各种基于OpenWrt或使用OpenWrt二次定制开发的路由器设备<br>
~支持各种运行标准Linux系统如Debian/CenOS/Armbian等的设备<br>
~兼容Padavan固件保守模式、潘多拉固件以及华硕/梅林固件<br>
~兼容各类使用Linux内核定制开发的各类型设备<br>
- **多内核支持**:在 Shell 环境下便捷管理及切换 **mihomo****sing-box** 内核。
- **灵活配置管理**:支持在线导入订阅连结及配置文件,简化配置流程。
- **自动化任务**:支持配置定时任务,实现配置文件与规则的自动定时更新。
- **图形化面板**:支持在线安装并使用本地 Web 面板Dashboard直观管理内置规则与流量。
- **多模式运行**:支持路由模式、本机模式等多种流量转发模式切换。
- **一键维护**:内置脚本在线更新功能,保持版本与功能的及时更迭。
——————————<br>
~更多设备支持请提issue或前往TG群反馈需提供设备名称及运行uname -a返回的设备核心信息<br>
## :computer: 设备支持
## 常见问题
ShellCrash 旨在兼容绝大多数基于 Linux 内核的网络设备
[ShellCrash常见问题 | Juewuy's Blog](https://juewuy.github.io/chang-jian-wen-ti/)
* **路由器设备**:支持各种基于 OpenWrt 或其二次开发固件(如 小米路由、网件路由等设备)。
* **Linux 服务器**:支持运行标准 Linux/GNU发行版如 Debian、CentOS、Armbian、Ubuntu 等)的设备。
* **第三方固件**:兼容 Padavan保守模式、潘多拉固件以及华硕/梅林固件。
* **其他设备**兼容各种基于Linux/GNU或者Linux/busybox开发的设备。
* **Docker**部分可能不兼容的设备如群辉、PVE支持docker环境运行。
## 使用方式:
> 更多设备支持,请提交 [Issue](https://github.com/juewuy/ShellCrash/issues) 或前往 [Telegram 群组](https://t.me/ShellClash) 反馈(请附上设备型号及 `uname -a` 命令的输出信息)。
~确认设备已经开启SSH并获取root权限带GUI桌面的Linux设备可使用自带终端安装<br>
~使用SSH连接工具如puttyJuiceSSH系统自带终端等路由器或Linux设备的SSH管理界面或终端界面
---
~之后在SSH界面执行目标设备对应的安装命令并按照后续提示完成安装<br>
## :hammer_and_wrench: 安装指南
### 在线安装:<br>
> [!TIP]
> 若遇到连接失败或SSL相关问题请尝试切换至其他安装镜像站。
**如无法连接或出现SSL连接错误请尝试更换各种不同的安装源**<br>
### 前置条件
1. 确保设备已开启 **SSH** 并获得 **Root 权限**(带图形介面的 Linux 系统可直接使用终端)。
2. 使用 SSH 工具(如 Putty、JuiceSSH、或系统自带终端连接至设备。
~**标准Linux设备安装**<br>
### :penguin: 标准 Linux 设备安装
```shell
sudo -i #切换到root用户,如果需要密码,请输入密码
export url='https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master' && wget -q --no-check-certificate -O /tmp/install.sh $url/install.sh && bash /tmp/install.sh && source /etc/profile &> /dev/null
```
或者
```shell
sudo -i #切换到root用户如果需要密码请输入密码
export url='https://gh.jwsc.eu.org/master' && bash -c "$(curl -kfsSl $url/install.sh)" && source /etc/profile &> /dev/null
> [!IMPORTANT]
> 请以 root 用户进行安装。
> 使用 wget 安装jsDelivr CDN 源)
```sh
export url='https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master' \
&& wget -q --no-check-certificate -O /tmp/install.sh $url/install.sh \
&& bash /tmp/install.sh \
&& . /etc/profile &> /dev/null
```
~**路由设备使用curl安装**<br>
> 使用 curl 安装(作者私人源)
```shell
#GitHub源(可能需要代理)
export url='https://raw.githubusercontent.com/juewuy/ShellCrash/master' && sh -c "$(curl -kfsSl $url/install.sh)" && source /etc/profile &> /dev/null
```
或者
```shell
#jsDelivrCDN源
export url='https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master' && sh -c "$(curl -kfsSl $url/install.sh)" && source /etc/profile &> /dev/null
```
或者
```shell
#作者私人源
export url='https://gh.jwsc.eu.org/master' && sh -c "$(curl -kfsSl $url/install.sh)" && source /etc/profile &> /dev/null
```sh
export url='https://gh.jwsc.eu.org/master' \
&& bash -c "$(curl -kfsSl $url/install.sh)" \
&& . /etc/profile &> /dev/null
```
~**路由设备使用wget安装**<br>
### :satellite: 路由设备安装
```Shell
#GitHub源(可能需要代理)
export url='https://raw.githubusercontent.com/juewuy/ShellCrash/master' && wget -q --no-check-certificate -O /tmp/install.sh $url/install.sh && sh /tmp/install.sh && source /etc/profile &> /dev/null
```
或者
```shell
#jsDelivrCDN源
export url='https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master' && wget -q --no-check-certificate -O /tmp/install.sh $url/install.sh && sh /tmp/install.sh && source /etc/profile &> /dev/null
**使用 `curl` 安装:**
> GitHub 源(推荐海外环境或具备代理环境使用)
```sh
export url='https://raw.githubusercontent.com/juewuy/ShellCrash/master' \
&& sh -c "$(curl -kfsSl $url/install.sh)" \
&& . /etc/profile &> /dev/null
```
~**老旧设备使用低版本wge安装**<br>
> 或 jsDelivr CDN 源
```Shell
#作者私人http内测源
export url='http://t.jwsc.eu.org' && wget -q -O /tmp/install.sh $url/install.sh && sh /tmp/install.sh && source /etc/profile &> /dev/null
```sh
export url='https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master' \
&& sh -c "$(curl -kfsSl $url/install.sh)" \
&& . /etc/profile &> /dev/null
```
##### ~**虚拟机安装:**<br>
> 或作者私人源
```sh
export url='https://gh.jwsc.eu.org/master' \
&& sh -c "$(curl -kfsSl $url/install.sh)" \
&& . /etc/profile &> /dev/null
```
虚拟机环境强烈建议使用Alpine镜像安装<br>
**使用 `wget` 安装:**
> GitHub 源(推荐海外环境或具备代理环境使用)
```sh
export url='https://raw.githubusercontent.com/juewuy/ShellCrash/master' \
&& wget -q --no-check-certificate -O /tmp/install.sh $url/install.sh \
&& sh /tmp/install.sh \
&& . /etc/profile &> /dev/null
```
```shell
#安装必要依赖
> 或 jsDelivr CDN 源
```sh
export url='https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master' \
&& wget -q --no-check-certificate -O /tmp/install.sh $url/install.sh \
&& sh /tmp/install.sh \
&& . /etc/profile &> /dev/null
```
### :pager: 老旧设备使用低版本 `wget` 安装
> 作者私人 http 内测源
```sh
export url='http://t.jwsc.eu.org' \
&& wget -q -O /tmp/install.sh $url/install.sh \
&& sh /tmp/install.sh \
&& . /etc/profile &> /dev/null
```
### :cloud: 虚拟机
- **Alpine Linux 虚拟机**:强烈建议使用 Alpine 镜像以获得最佳兼容性
```sh
# 安装必要依赖
apk add --no-cache wget openrc ca-certificates tzdata nftables iproute2 dcron
#执行安装命令
export url='https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master' && wget -q --no-check-certificate -O /tmp/install.sh $url/install.sh && sh /tmp/install.sh && source /etc/profile &> /dev/null
# 执行安装命令
export url='https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master' \
&& wget -q --no-check-certificate -O /tmp/install.sh $url/install.sh \
&& sh /tmp/install.sh \
&& . /etc/profile &> /dev/null
```
##### ~Docker安装<br>
### :whale: Docker
请前往[ShellCrash官方Docker镜像](https://hub.docker.com/r/juewuy/shellcrash)
请访问官方 Docker 镜像
### **本地安装:**<br>
- [ShellCrash on Docker Hub](https://hub.docker.com/r/juewuy/shellcrash)
如使用在线安装出现问题,请参考:[本地安装ShellCrash的教程 | Juewuy's Blog](https://juewuy.github.io/bdaz) 使用本地安装!<br>
### 使用脚本:<br>
### :package: 本地安装
安装完成管理脚本后,执行如下命令使用~
若无法进行在线安装,请参照以下指南执行本地安装:
```Shell
crash #进入对话
crash -h #帮助列表
```
- [本地安装ShellCrash教程 | Juewuy's Blog](https://juewuy.github.io/bdaz)
#### **运行时的额外依赖**<br>
---
> 大部分的设备/系统都已经预装了以下的大部分依赖,使用时如无影响可以无视之
## :book: 使用说明
安装完成后,在终端输入以下指令即可启动管理界面:
```shell
curl/wget 必须 全部缺少时无法在线安装及更新,无法使用节点保存功能
iptables/nftables 重要 缺少时只能使用纯净模式
crontab 较低 缺少时无法启用定时任务功能
net-tools 极低 缺少时无法正常检测端口占用
ubus/iproute-doc 极低 缺少时无法正常获取本机host地址
crash # 启动脚本交互选单
crash -h # 查看命令帮助列表
```
### 运行依赖说明
| 依赖组件 | 必要性 | 说明 |
| :--- | :--- | :--- |
| curl / wget | 必须 | 缺少时将无法进行节点保存、在线安装及更新操作 |
| iptables / nftables | 重要 | 缺少时仅能运行于纯淨模式 |
| crontab | 较低 | 缺少时定时任务功能将失效 |
| net-tools | 极低 | 缺少时无法自动检测端口占用 |
| ubus / iproute-doc | 极低 | 缺少时无法自动获取本机 Host 地址 |
---
更新日志:
--
## :link: 相关链接
- 常见问题:[Juewuy's Blog](https://juewuy.github.io/chang-jian-wen-ti/)
- 更新日志:[Release History](https://github.com/juewuy/ShellCrash/releases)
- 交流反馈:[Telegram 讨论组](https://t.me/ShellClash)
### [点击查看](https://github.com/juewuy/ShellCrash/releases)
---
交流反馈:
--
### [TG讨论组](https://t.me/ShellClash)
## :scroll: 许可协议
机场推荐:
--
本项目采用[GNU通用公共许可证第3.0版](LICENSE.txt)授权。
#### [Dler-墙洞,多年稳定运行,功能齐全](https://dler.pro/auth/register?affid=89698)<br>
---
#### [大米-群友力荐,流媒体解锁,月付推荐](https://1s.bigmeok.me/user#/register?code=2PuWY9I7)<br>
## :airplane: 机场推荐
- [**Dler-墙洞**](https://dler.pro/auth/register?affid=89698),多年稳定运行,功能齐全。
- [**大米**](https://1s.bigmeok.me/user#/register?code=2PuWY9I7),群友力荐,流媒体解锁,月付推荐。

Binary file not shown.

Binary file not shown.

View File

@@ -1,4 +1,4 @@
meta_v=v1.19.17
singboxr_v=1.13.0-alpha.27
versionsh=1.9.3release
versionsh=1.9.5alpha6.1
GeoIP_v=20251205

View File

@@ -15,7 +15,7 @@ docker run -d \
--name shellcrash \
-p 7890:7890 \
-p 9999:9999 \
shellcrash:latest
juewuy/shellcrash:latest
```
------
@@ -59,7 +59,7 @@ docker run -d \
--cap-add SYS_ADMIN \
--device /dev/net/tun:/dev/net/tun \
--restart unless-stopped \
shellcrash:latest
juewuy/shellcrash:latest
```
### 3. 配置需要路由的设备

View File

@@ -2,8 +2,8 @@ version: "3.9"
services:
shellclash:
image: shellclash:latest
container_name: shellclash
image: juewuy/shellcrash:latest
container_name: shellcrash
networks:
macvlan_lan:
ipv4_address: 192.168.31.222

View File

@@ -1,20 +1,25 @@
#! /bin/bash
#!/bin/sh
# Copyright (C) Juewuy
[ -z "$url" ] && url="https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@dev"
type bash &>/dev/null && shtype=bash || shtype=sh
[ -n "$(echo -e | grep e)" ] && echo=echo || echo='echo -e'
echo "***********************************************"
echo "** 欢迎使用 **"
echo "** ShellCrash **"
echo "** by Juewuy **"
echo "***********************************************"
#内置工具
dir_avail() {
df $2 $1 | awk '{ for(i=1;i<=NF;i++){ if(NR==1){ arr[i]=$i; }else{ arr[i]=arr[i]" "$i; } } } END{ for(i=1;i<=NF;i++){ print arr[i]; } }' | grep -E 'Ava|可用' | awk '{print $2}'
language=chs
[ -z "$url" ] && url="https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master"
# 内置工具
cecho() {
printf '%b\n' "$*"
}
ckcmd() { #检查命令
if command -v sh >/dev/null 2>&1;then
dir_avail() {
df -h >/dev/null 2>&1 && h="$2"
df -P $h "${1:-.}" 2>/dev/null | awk 'NR==2 {print $4}'
}
ckcmd() {
if command -v sh >/dev/null 2>&1; then
command -v "$1" >/dev/null 2>&1
else
type "$1" >/dev/null 2>&1
@@ -26,7 +31,7 @@ webget() {
if curl --version >/dev/null 2>&1; then
[ "$3" = "echooff" ] && progress='-s' || progress='-#'
[ -z "$4" ] && redirect='-L' || redirect=''
result=$(curl -w %{http_code} --connect-timeout 5 $progress $redirect -ko $1 $2)
result=$(curl -w %{http_code} --connect-timeout 5 "$progress" "$redirect" -ko "$1" "$2")
[ -n "$(echo $result | grep -e ^2)" ] && result="200"
else
if wget --version >/dev/null 2>&1; then
@@ -37,293 +42,331 @@ webget() {
fi
[ "$3" = "echoon" ] && progress=''
[ "$3" = "echooff" ] && progress='-q'
wget $progress $redirect $certificate $timeout -O $1 $2
wget "$progress" "$redirect" "$certificate" "$timeout" -O "$1" "$2"
[ $? -eq 0 ] && result="200"
fi
}
error_down() {
$echo "请参考 \033[32mhttps://github.com/juewuy/ShellCrash/blob/master/README_CN.md"
$echo "\033[33m使用其他安装源重新安装\033[0m"
cecho "请参考 \033[32mhttps://github.com/juewuy/ShellCrash/blob/master/README_CN.md"
cecho "\033[33m使用其他安装源重新安装\033[0m"
}
#安装及初始化
# 安装及初始化
set_alias() {
echo "-----------------------------------------------"
$echo "\033[36m请选择一个别名或使用自定义别名\033[0m"
echo "-----------------------------------------------"
$echo " 1 【\033[32mcrash\033[0m】"
$echo " 2 【\033[32m sc \033[0m】"
$echo " 3 【\033[32m mm \033[0m】"
$echo " 0 退出安装"
echo "-----------------------------------------------"
read -p "请输入相应数字或自定义别名 > " res
case "$res" in
1) my_alias=crash ;;
2) my_alias=sc ;;
3) my_alias=mm ;;
*) my_alias=$res ;;
esac
cmd=$(ckcmd "$my_alias" | grep 'menu.sh')
ckcmd "$my_alias" && [ -z "$cmd" ] && {
$echo "\033[33m此别名和当前系统内置命令/别名冲突,请换一个!\033[0m"
sleep 1
set_alias
}
while true; do
echo "-----------------------------------------------"
cecho "\033[36m请选择一个别名或使用自定义别名\033[0m"
echo "-----------------------------------------------"
cecho " 1 【\033[32mcrash\033[0m】"
cecho " 2 【\033[32m sc \033[0m】"
cecho " 3 【\033[32m mm \033[0m】"
cecho " 0 退出安装"
echo "-----------------------------------------------"
read -p "请输入相应数字或自定义别名 > " res
case "$res" in
0)
echo "安装已取消"
exit 1
;;
1)
my_alias=crash
;;
2)
my_alias=sc
;;
3)
my_alias=mm
;;
*)
my_alias=$res
;;
esac
cmd=$(ckcmd "$my_alias" | grep 'menu.sh')
ckcmd "$my_alias" && [ -z "$cmd" ] && {
cecho "\033[33m此别名和当前系统内置命令/别名冲突,请换一个!\033[0m"
sleep 1
continue
}
break
done
}
gettar() {
webget /tmp/ShellCrash.tar.gz "$url/ShellCrash.tar.gz"
webget /tmp/ShellCrash.tar.gz "$url/ShellCrash.tar.gz" >/dev/null 2>&1
if [ "$result" != "200" ]; then
$echo "\033[33m文件下载失败\033[0m"
cecho "\033[33m文件下载失败\033[0m"
error_down
exit 1
else
$CRASHDIR/start.sh stop 2>/dev/null
#解压
"$CRASHDIR"/start.sh stop 2>/dev/null
# 解压
echo "-----------------------------------------------"
echo 开始解压文件!
mkdir -p $CRASHDIR >/dev/null
tar -zxf '/tmp/ShellCrash.tar.gz' -C $CRASHDIR/ || tar -zxf '/tmp/ShellCrash.tar.gz' --no-same-owner -C $CRASHDIR/
if [ -s $CRASHDIR/init.sh ]; then
echo "开始解压文件!"
mkdir -p "$CRASHDIR" >/dev/null
tar -zxf '/tmp/ShellCrash.tar.gz' -C "$CRASHDIR"/ || tar -zxf '/tmp/ShellCrash.tar.gz' --no-same-owner -C "$CRASHDIR"/
if [ -s "$CRASHDIR"/init.sh ]; then
set_alias
. $CRASHDIR/init.sh >/dev/null
[ "$?" != 0 ] && $echo "\033[33m初始化失败请尝试本地安装\033[0m" && exit 1
. "$CRASHDIR"/init.sh >/dev/null
[ "$?" != 0 ] && cecho "\033[33m初始化失败请尝试本地安装\033[0m" && exit 1
else
rm -rf /tmp/ShellCrash.tar.gz
$echo "\033[33m文件解压失败\033[0m"
cecho "\033[33m文件解压失败\033[0m"
error_down
exit 1
fi
fi
}
setdir() {
set_usb_dir() {
$echo "请选择安装目录"
set_usb_dir() {
while true; do
cecho "请选择安装目录"
du -hL /mnt | awk '{print " "NR" "$2" "$1}'
read -p "请输入相应数字 > " num
dir=$(du -hL /mnt | awk '{print $2}' | sed -n "$num"p)
if [ -z "$dir" ]; then
$echo "\033[31m输入错误请重新设置\033[0m"
set_usb_dir
cecho "\033[31m输入错误请重新设置\033[0m"
continue
fi
}
set_asus_dir() {
echo -e "请选择U盘目录"
du -hL /tmp/mnt | awk -F/ 'NF<=4' | awk '{print " "NR" "$2" "$1}'
read -p "请输入相应数字 > " num
dir=$(du -hL /tmp/mnt | awk -F/ 'NF<=4' | awk '{print $2}' | sed -n "$num"p)
if [ ! -f "$dir/asusware.arm/etc/init.d/S50downloadmaster" ]; then
echo -e "\033[31m未找到下载大师自启文件$dir/asusware.arm/etc/init.d/S50downloadmaster请检查设置\033[0m"
set_asus_dir
fi
}
set_cust_dir() {
break 1
done
}
set_xiaomi_dir() {
cecho "\033[33m检测到当前设备为小米官方系统请选择安装位置\033[0m"
[ -d /data ] && cecho " 1 安装到 /data 目录,剩余空间:$(dir_avail /data -h)(支持软固化功能)"
[ -d /userdisk ] && cecho " 2 安装到 /userdisk 目录,剩余空间:$(dir_avail /userdisk -h)(支持软固化功能)"
[ -d /data/other_vol ] && cecho " 3 安装到 /data/other_vol 目录,剩余空间:$(dir_avail /data/other_vol -h)(支持软固化功能)"
cecho " 4 安装到自定义目录(不推荐,不明勿用!)"
cecho " 0 退出安装"
echo "-----------------------------------------------"
read -p "请输入相应数字 > " num
case "$num" in
1)
dir=/data
;;
2)
dir=/userdisk
;;
3)
dir=/data/other_vol
;;
4)
set_cust_dir
;;
*)
exit 1
;;
esac
}
set_asus_usb() {
while true; do
echo -e "请选择U盘目录"
du -hL /tmp/mnt | awk -F/ 'NF<=4' | awk '{print " "NR" "$2" "$1}'
read -p "请输入相应数字 > " num
dir=$(du -hL /tmp/mnt | awk -F/ 'NF<=4' | awk '{print $2}' | sed -n "$num"p)
if [ ! -f "$dir/asusware.arm/etc/init.d/S50downloadmaster" ]; then
echo -e "\033[31m未找到下载大师自启文件$dir/asusware.arm/etc/init.d/S50downloadmaster请检查设置\033[0m"
sleep 1
else
break
fi
done
}
set_asus_dir() {
cecho "\033[33m检测到当前设备为华硕固件请选择安装方式\033[0m"
cecho " 1 基于U盘+下载大师安装(支持所有固件限ARM设备须插入U盘或移动硬盘)"
cecho " 2 基于自启脚本安装(仅支持部分梅林固件)"
cecho " 0 退出安装"
echo "-----------------------------------------------"
read -p "请输入相应数字 > " num
case "$num" in
1)
echo -e "请先在路由器网页后台安装下载大师并启用,之后选择外置存储所在目录!"
sleep 2
set_asus_usb
;;
2)
cecho "如开机无法正常自启请重新使用U盘+下载大师安装!"
sleep 2
dir=/jffs
;;
*)
exit 1
;;
esac
}
set_cust_dir() {
while true; do
echo "-----------------------------------------------"
echo '可用路径 剩余空间:'
echo '可用路径 剩余空间'
df -h | awk '{print $6,$4}' | sed 1d
echo '路径是必须带 / 的格式,注意写入虚拟内存(/tmp,/opt,/sys...)的文件会在重启后消失!!!'
read -p "请输入自定义路径 > " dir
if [ "$(dir_avail $dir)" = 0 ] || [ -n "$(echo $dir | grep -E 'tmp|opt|sys')" ]; then
$echo "\033[31m路径错误请重新设置\033[0m"
set_cust_dir
if [ "$(dir_avail "$dir")" = 0 ] || [ -n "$(echo "$dir" | grep -Eq '^/(tmp|opt|sys)(/|$)')" ]; then
cecho "\033[31m路径错误请重新设置\033[0m"
continue
fi
}
echo "-----------------------------------------------"
$echo "\033[33m注意安装ShellCrash至少需要预留约1MB的磁盘空间\033[0m"
if [ -n "$systype" ]; then
[ "$systype" = "Padavan" ] && dir=/etc/storage
[ "$systype" = "mi_snapshot" ] && {
$echo "\033[33m检测到当前设备为小米官方系统请选择安装位置\033[0m"
[ -d /data ] && $echo " 1 安装到 /data 目录,剩余空间:$(dir_avail /data -h)(支持软固化功能)"
[ -d /userdisk ] && $echo " 2 安装到 /userdisk 目录,剩余空间:$(dir_avail /userdisk -h)(支持软固化功能)"
[ -d /data/other_vol ] && $echo " 3 安装到 /data/other_vol 目录,剩余空间:$(dir_avail /data/other_vol -h)(支持软固化功能)"
$echo " 4 安装到自定义目录(不推荐,不明勿用!)"
$echo " 0 退出安装"
echo "-----------------------------------------------"
read -p "请输入相应数字 > " num
case "$num" in
1)
dir=/data
;;
2)
dir=/userdisk
;;
3)
dir=/data/other_vol
;;
4)
set_cust_dir
;;
*)
exit 1
;;
esac
}
[ "$systype" = "asusrouter" ] && {
$echo "\033[33m检测到当前设备为华硕固件请选择安装方式\033[0m"
$echo " 1 基于USB设备安装(限23年9月之前固件须插入\033[31m任意\033[0mUSB设备)"
$echo " 2 基于自启脚本安装(仅支持梅林及部分非koolshare官改固件)"
$echo " 3 基于U盘+下载大师安装(支持所有固件限ARM设备须插入U盘或移动硬盘)"
$echo " 0 退出安装"
echo "-----------------------------------------------"
read -p "请输入相应数字 > " num
case "$num" in
1)
read -p "将脚本安装到USB存储/系统闪存?(1/0) > " res
[ "$res" = "1" ] && set_usb_dir || dir=/jffs
usb_status=1
;;
2)
$echo "如无法正常开机启动请重新使用USB方式安装"
sleep 2
dir=/jffs
;;
3)
echo -e "请先在路由器网页后台安装下载大师并启用,之后选择外置存储所在目录!"
sleep 2
set_asus_dir
;;
*)
exit 1
;;
esac
}
[ "$systype" = "ng_snapshot" ] && dir=/tmp/mnt
else
$echo " 1 在\033[32m/etc目录\033[0m下安装(适合root用户)"
$echo " 2 在\033[32m/usr/share目录\033[0m下安装(适合Linux系统)"
$echo " 3 在\033[32m当前用户目录\033[0m下安装(适合非root用户)"
$echo " 4 在\033[32m外置存储\033[0m中安装"
$echo " 5 手动设置安装目录"
$echo " 0 退出安装"
echo "----------------------------------------------"
read -p "请输入相应数字 > " num
#设置目录
case "$num" in
1)
dir=/etc
;;
2)
dir=/usr/share
;;
3)
dir=~/.local/share
mkdir -p ~/.config/systemd/user
;;
4)
set_usb_dir
;;
5)
set_cust_dir
;;
*)
echo "安装已取消"
exit 1
;;
esac
fi
break 1
done
}
if [ ! -w $dir ]; then
$echo "\033[31m没有$dir目录写入权限!请重新设置!\033[0m" && sleep 1 && setdir
else
$echo "目标目录\033[32m$dir\033[0m空间剩余$(dir_avail $dir -h)"
read -p "确认安装?(1/0) > " res
[ "$res" = "1" ] && CRASHDIR=$dir/ShellCrash || setdir
fi
setdir() {
while true; do
echo "-----------------------------------------------"
cecho "\033[33m注意安装ShellCrash至少需要预留约1MB的磁盘空间\033[0m"
case "$systype" in
Padavan) dir=/etc/storage ;;
mi_snapshot) set_xiaomi_dir ;;
asusrouter) set_asus_dir ;;
ng_snapshot) dir=/tmp/mnt ;;
*)
cecho " 1 在\033[32m/etc目录\033[0m下安装(适合root用户)"
cecho " 2 在\033[32m/usr/share目录\033[0m下安装(适合Linux系统)"
cecho " 3 在\033[32m当前用户目录\033[0m下安装(适合非root用户)"
cecho " 4 在\033[32m外置存储\033[0m中安装"
cecho " 5 手动设置安装目录"
cecho " 0 退出安装"
echo "----------------------------------------------"
read -p "请输入相应数字 > " num
# 设置目录
case "$num" in
1)
dir=/etc
;;
2)
dir=/usr/share
;;
3)
dir=~/.local/share
mkdir -p ~/.config/systemd/user
;;
4)
set_usb_dir
;;
5)
set_cust_dir
;;
*)
echo "安装已取消"
exit 1
;;
esac
;;
esac
if [ ! -w "$dir" ]; then
cecho "\033[31m没有$dir目录写入权限!请重新设置!\033[0m"
sleep 1
else
cecho "目标目录\033[32m$dir\033[0m空间剩余$(dir_avail "$dir" -h)"
read -p "确认安装?(1/0) > " res
if [ "$res" = "1" ]; then
CRASHDIR="$dir"/ShellCrash
break
fi
fi
done
}
install() {
echo "-----------------------------------------------"
echo 开始从服务器获取安装文件!
echo "开始从服务器获取安装文件!"
echo "-----------------------------------------------"
gettar
echo "-----------------------------------------------"
echo "ShellCrash 已经安装成功!"
[ "$profile" = "~/.bashrc" ] && echo "请执行【. ~/.bashrc > /dev/null】命令以加载环境变量!"
[ -n "$(ls -l /bin/sh | grep -oE 'zsh')" ] && echo "请执行【. ~/.zshrc > /dev/null】命令以加载环境变量!"
[ "$profile" = "~/.bashrc" ] && echo "请执行【. ~/.bashrc > /dev/null】命令以更新环境变量!"
[ -n "$(ls -l /bin/sh | grep -oE 'zsh')" ] && echo "请执行【. ~/.zshrc > /dev/null】命令以更新环境变量!"
echo "-----------------------------------------------"
$echo "\033[33m输入\033[30;47m $my_alias \033[0;33m命令即可管理\033[0m"
cecho "\033[33m输入\033[30;47m $my_alias \033[0;33m命令即可管理\033[0m"
echo "-----------------------------------------------"
}
setversion() {
echo "-----------------------------------------------"
$echo "\033[33m请选择想要安装的版本\033[0m"
$echo " 1 \033[32m公测版(推荐)\033[0m"
$echo " 2 \033[36m稳定版\033[0m"
$echo " 3 \033[31m开发版\033[0m"
cecho "\033[33m请选择想要安装的版本\033[0m"
cecho " 1 \033[32m公测版(推荐)\033[0m"
cecho " 2 \033[36m稳定版\033[0m"
cecho " 3 \033[31m开发版\033[0m"
echo "-----------------------------------------------"
read -p "请输入相应数字 > " num
case "$num" in
2)
url=$(echo $url | sed 's/master/stable/')
;;
3)
url=$(echo $url | sed 's/master/dev/')
;;
1) release_type=master ;;
2) release_type=stable ;;
3) release_type=dev ;;
*) ;;
esac
url=$(echo "$url" | sed "s/master/$release_type/")
}
#特殊固件识别及标记
[ -f "/etc/storage/started_script.sh" ] && {
systype=Padavan #老毛子固件
initdir='/etc/storage/started_script.sh'
# 安装检查
check_systype() {
[ -f "/etc/storage/started_script.sh" ] && {
systype=Padavan #老毛子固件
initdir='/etc/storage/started_script.sh'
}
[ -d "/jffs" ] && {
systype=asusrouter #华硕固件
[ -f "/jffs/.asusrouter" ] && initdir='/jffs/.asusrouter'
[ -d "/jffs/scripts" ] && initdir='/jffs/scripts/nat-start'
}
[ -f "/data/etc/crontabs/root" ] && systype=mi_snapshot #小米设备
[ -w "/var/mnt/cfg/firewall" ] && systype=ng_snapshot #NETGEAR设备
}
[ -d "/jffs" ] && {
systype=asusrouter #华硕固件
[ -f "/jffs/.asusrouter" ] && initdir='/jffs/.asusrouter'
[ -d "/jffs/scripts" ] && initdir='/jffs/scripts/nat-start'
check_user() {
if [ "$USER" != "root" ] && [ -z "$systype" ]; then
echo "当前用户:$USER"
cecho "\033[31m请尽量使用root用户不要直接使用sudo命令执行安装!\033[0m"
echo "-----------------------------------------------"
read -p "仍要安装?可能会产生未知错误!(1/0) > " res
[ "$res" != "1" ] && exit 1
fi
}
[ -f "/data/etc/crontabs/root" ] && systype=mi_snapshot #小米设备
[ -w "/var/mnt/cfg/firewall" ] && systype=ng_snapshot #NETGEAR设备
check_version() {
echo "$url" | grep -q 'master' && setversion
webget /tmp/version "$url/version" echooff
[ "$result" = "200" ] && versionsh=$(cat /tmp/version)
rm -rf /tmp/version
#检查root权限
if [ "$USER" != "root" -a -z "$systype" ]; then
echo 当前用户:$USER
$echo "\033[31m请尽量使用root用户不要直接使用sudo命令执行安装!\033[0m"
echo "-----------------------------------------------"
read -p "仍要安装?可能会产生未知错误!(1/0) > " res
[ "$res" != "1" ] && exit 1
fi
# 输出
cecho "最新版本:\033[32m$versionsh\033[0m"
echo "-----------------------------------------------"
cecho "\033[44m如遇问题请加TG群反馈\033[42;30m t.me/ShellClash \033[0m"
cecho "\033[37m支持各种基于openwrt的路由器设备"
cecho "\033[33m支持Debian、Centos等标准Linux系统\033[0m"
}
check_dir() {
if [ -n "$CRASHDIR" ]; then
echo "-----------------------------------------------"
cecho "检测到旧的安装目录\033[36m$CRASHDIR\033[0m是否覆盖安装"
cecho "\033[32m覆盖安装时不会移除配置文件\033[0m"
echo " 1 覆盖安装"
echo " 2 卸载旧版本并安装"
echo " 0 取消安装"
read -p "请输入相应数字 > " num
case "$num" in
1)
install
;;
2)
[ "$CRASHDIR" != "/" ] && rm -rf "$CRASHDIR"
echo "-----------------------------------------------"
cecho "\033[31m 旧版本文件已卸载!\033[0m"
setdir
install
;;
9)
echo "测试模式,变更安装位置 $CRASHDIR"
setdir
install
;;
*)
cecho "\033[31m已取消安装\033[0m"
exit 1
;;
esac
else
setdir
install
fi
}
if [ -n "$(echo $url | grep master)" ]; then
setversion
fi
#获取版本信息
webget /tmp/version "$url/version" echooff
[ "$result" = "200" ] && versionsh=$(cat /tmp/version)
rm -rf /tmp/version
#输出
$echo "最新版本:\033[32m$versionsh\033[0m"
echo "-----------------------------------------------"
$echo "\033[44m如遇问题请加TG群反馈\033[42;30m t.me/ShellClash \033[0m"
$echo "\033[37m支持各种基于openwrt的路由器设备"
$echo "\033[33m支持Debian、Centos等标准Linux系统\033[0m"
if [ -n "$CRASHDIR" ]; then
echo "-----------------------------------------------"
$echo "检测到旧的安装目录\033[36m$CRASHDIR\033[0m是否覆盖安装"
$echo "\033[32m覆盖安装时不会移除配置文件\033[0m"
read -p "覆盖安装/卸载旧版本?(1/0) > " res
case "$res" in
1)
install
;;
0)
rm -rf $CRASHDIR
echo "-----------------------------------------------"
$echo "\033[31m 旧版本文件已卸载!\033[0m"
setdir
install
;;
9)
echo "测试模式,变更安装位置"
setdir
install
;;
*)
$echo "\033[31m输入错误已取消安装\033[0m"
exit 1
;;
esac
else
setdir
install
fi
check_systype
check_user
check_version
check_dir

372
install_en.sh Normal file
View File

@@ -0,0 +1,372 @@
#!/bin/sh
# Copyright (C) Juewuy
echo "***********************************************"
echo "** Welcome to **"
echo "** ShellCrash **"
echo "** by Juewuy **"
echo "***********************************************"
language=en
[ -z "$url" ] && url="https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master"
# Internal Tools
cecho() {
printf '%b\n' "$*"
}
dir_avail() {
df -h >/dev/null 2>&1 && h="$2"
df -P $h "${1:-.}" 2>/dev/null | awk 'NR==2 {print $4}'
}
ckcmd() {
if command -v sh >/dev/null 2>&1; then
command -v "$1" >/dev/null 2>&1
else
type "$1" >/dev/null 2>&1
fi
}
webget() {
# Parameter [$1] Download Path, [$2] Online URL
# Parameter [$3] Display Output, [$4] Disable Redirects
if curl --version >/dev/null 2>&1; then
[ "$3" = "echooff" ] && progress='-s' || progress='-#'
[ -z "$4" ] && redirect='-L' || redirect=''
result=$(curl -w %{http_code} --connect-timeout 5 "$progress" "$redirect" -ko "$1" "$2")
[ -n "$(echo $result | grep -e ^2)" ] && result="200"
else
if wget --version >/dev/null 2>&1; then
[ "$3" = "echooff" ] && progress='-q' || progress='-q --show-progress'
[ "$4" = "rediroff" ] && redirect='--max-redirect=0' || redirect=''
certificate='--no-check-certificate'
timeout='--timeout=3'
fi
[ "$3" = "echoon" ] && progress=''
[ "$3" = "echooff" ] && progress='-q'
wget "$progress" "$redirect" "$certificate" "$timeout" -O "$1" "$2"
[ $? -eq 0 ] && result="200"
fi
}
error_down() {
cecho "Please refer to \033[32mhttps://github.com/juewuy/ShellCrash/blob/master/README.md"
cecho "\033[33mUse an alternative source to reinstall!\033[0m"
}
# Installation and Initialization
set_alias() {
while true; do
echo "-----------------------------------------------"
cecho "\033[36mPlease select an alias or enter a custom one:\033[0m"
echo "-----------------------------------------------"
cecho " 1 【\033[32mcrash\033[0m】"
cecho " 2 【\033[32m sc \033[0m】"
cecho " 3 【\033[32m mm \033[0m】"
cecho " 0 Exit Installation"
echo "-----------------------------------------------"
read -p "Enter number or custom alias > " res
case "$res" in
0)
echo "Installation cancelled"
exit 1
;;
1)
my_alias=crash
;;
2)
my_alias=sc
;;
3)
my_alias=mm
;;
*)
my_alias=$res
;;
esac
cmd=$(ckcmd "$my_alias" | grep 'menu.sh')
ckcmd "$my_alias" && [ -z "$cmd" ] && {
cecho "\033[33mThis alias conflicts with a system command; please choose another!\033[0m"
sleep 1
continue
}
break
done
}
gettar() {
webget /tmp/ShellCrash.tar.gz "$url/ShellCrash.tar.gz" >/dev/null 2>&1
if [ "$result" != "200" ]; then
cecho "\033[33mFile download failed!\033[0m"
error_down
exit 1
else
"$CRASHDIR"/start.sh stop 2>/dev/null
# Extract
echo "-----------------------------------------------"
echo "Starting file extraction!"
mkdir -p "$CRASHDIR" >/dev/null
tar -zxf '/tmp/ShellCrash.tar.gz' -C "$CRASHDIR"/ || tar -zxf '/tmp/ShellCrash.tar.gz' --no-same-owner -C "$CRASHDIR"/
if [ -s "$CRASHDIR"/init.sh ]; then
set_alias
. "$CRASHDIR"/init.sh >/dev/null
[ "$?" != 0 ] && cecho "\033[33mInitialization failed, try local installation!\033[0m" && exit 1
else
rm -rf /tmp/ShellCrash.tar.gz
cecho "\033[33mFile extraction failed!\033[0m"
error_down
exit 1
fi
fi
}
set_usb_dir() {
while true; do
cecho "Please select installation directory"
du -hL /mnt | awk '{print " "NR" "$2" "$1}'
read -p "Enter number > " num
dir=$(du -hL /mnt | awk '{print $2}' | sed -n "$num"p)
if [ -z "$dir" ]; then
cecho "\033[31mInvalid input! Please try again!\033[0m"
continue
fi
break 1
done
}
set_xiaomi_dir() {
cecho "\033[33mXiaomi device detected, please select installation location\033[0m"
[ -d /data ] && cecho " 1 Install to /data, Free space: $(dir_avail /data -h) (Supports soft-hardening)"
[ -d /userdisk ] && cecho " 2 Install to /userdisk, Free space: $(dir_avail /userdisk -h) (Supports soft-hardening)"
[ -d /data/other_vol ] && cecho " 3 Install to /data/other_vol, Free space: $(dir_avail /data/other_vol -h) (Supports soft-hardening)"
cecho " 4 Custom directory (Not recommended for beginners!)"
cecho " 0 Exit"
echo "-----------------------------------------------"
read -p "Enter number > " num
case "$num" in
1)
dir=/data
;;
2)
dir=/userdisk
;;
3)
dir=/data/other_vol
;;
4)
set_cust_dir
;;
*)
exit 1
;;
esac
}
set_asus_usb() {
while true; do
echo -e "Please select USB directory"
du -hL /tmp/mnt | awk -F/ 'NF<=4' | awk '{print " "NR" "$2" "$1}'
read -p "Enter number > " num
dir=$(du -hL /tmp/mnt | awk -F/ 'NF<=4' | awk '{print $2}' | sed -n "$num"p)
if [ ! -f "$dir/asusware.arm/etc/init.d/S50downloadmaster" ]; then
echo -e "\033[31mDownload Master startup file not found: $dir/asusware.arm/etc/init.d/S50downloadmaster. Check settings!\033[0m"
sleep 1
else
break
fi
done
}
set_asus_dir() {
cecho "\033[33mAsus firmware detected, please select installation method\033[0m"
cecho " 1 Via USB + Download Master (Supports all firmware, ARM only, USB required)"
cecho " 2 Via startup script (Merlin firmware only)"
cecho " 0 Exit"
echo "-----------------------------------------------"
read -p "Enter number > " num
case "$num" in
1)
echo -e "Please install and enable Download Master in the router web UI first, then select the storage directory!"
sleep 2
set_asus_usb
;;
2)
cecho "If auto-start fails after reboot, please use USB + Download Master method instead!"
sleep 2
dir=/jffs
;;
*)
exit 1
;;
esac
}
set_cust_dir() {
while true; do
echo "-----------------------------------------------"
echo 'Path | Free Space:'
df -h | awk '{print $6,$4}' | sed 1d
echo 'Path must start with "/". Files in virtual memory (/tmp, /opt, /sys...) will be lost on reboot!!!'
read -p "Enter custom path > " dir
if [ "$(dir_avail "$dir")" = 0 ] || [ -n "$(echo "$dir" | grep -Eq '^/(tmp|opt|sys)(/|$)')" ]; then
cecho "\033[31mInvalid path! Please try again!\033[0m"
continue
fi
break 1
done
}
setdir() {
while true; do
echo "-----------------------------------------------"
cecho "\033[33mNote: ShellCrash requires at least 1MB of disk space\033[0m"
case "$systype" in
Padavan) dir=/etc/storage ;;
mi_snapshot) set_xiaomi_dir ;;
asusrouter) set_asus_dir ;;
ng_snapshot) dir=/tmp/mnt ;;
*)
cecho " 1 Install in \033[32m/etc\033[0m (Best for root users)"
cecho " 2 Install in \033[32m/usr/share\033[0m (Standard Linux systems)"
cecho " 3 Install in \033[32mUser Directory\033[0m (Best for non-root users)"
cecho " 4 Install on \033[32mExternal Storage\033[0m"
cecho " 5 Manual path entry"
cecho " 0 Exit"
echo "----------------------------------------------"
read -p "Enter number > " num
# Set Dir
case "$num" in
1)
dir=/etc
;;
2)
dir=/usr/share
;;
3)
dir=~/.local/share
mkdir -p ~/.config/systemd/user
;;
4)
set_usb_dir
;;
5)
set_cust_dir
;;
*)
echo "Installation cancelled"
exit 1
;;
esac
;;
esac
if [ ! -w "$dir" ]; then
cecho "\033[31mNo write permission for $dir! Please reset!\033[0m"
sleep 1
else
cecho "Target directory: \033[32m$dir\033[0m | Free space: $(dir_avail "$dir" -h)"
read -p "Confirm installation? (1/0) > " res
if [ "$res" = "1" ]; then
CRASHDIR="$dir"/ShellCrash
break
fi
fi
done
}
install() {
echo "-----------------------------------------------"
echo "Retrieving installation files from server..."
echo "-----------------------------------------------"
gettar
echo "-----------------------------------------------"
echo "ShellCrash installed successfully!"
[ "$profile" = "~/.bashrc" ] && echo "Please run [. ~/.bashrc > /dev/null] to update environment variables!"
[ -n "$(ls -l /bin/sh | grep -oE 'zsh')" ] && echo "Please run [. ~/.zshrc > /dev/null] to update environment variables!"
echo "-----------------------------------------------"
cecho "\033[33mType \033[30;47m $my_alias \033[0;33m to start management dashboard!!!\033[0m"
echo "-----------------------------------------------"
}
setversion() {
echo "-----------------------------------------------"
cecho "\033[33mSelect version to install:\033[0m"
cecho " 1 \033[32mBeta (Recommended)\033[0m"
cecho " 2 \033[36mStable\033[0m"
cecho " 3 \033[31mDev (Unstable)\033[0m"
echo "-----------------------------------------------"
read -p "Enter number > " num
case "$num" in
1) release_type=master ;;
2) release_type=stable ;;
3) release_type=dev ;;
*) ;;
esac
url=$(echo "$url" | sed "s/master/$release_type/")
}
# Pre-Install Checks
check_systype() {
[ -f "/etc/storage/started_script.sh" ] && {
systype=Padavan # Padavan Firmware
initdir='/etc/storage/started_script.sh'
}
[ -d "/jffs" ] && {
systype=asusrouter # Asus Firmware
[ -f "/jffs/.asusrouter" ] && initdir='/jffs/.asusrouter'
[ -d "/jffs/scripts" ] && initdir='/jffs/scripts/nat-start'
}
[ -f "/data/etc/crontabs/root" ] && systype=mi_snapshot # Xiaomi device
[ -w "/var/mnt/cfg/firewall" ] && systype=ng_snapshot # NETGEAR device
}
check_user() {
if [ "$USER" != "root" ] && [ -z "$systype" ]; then
echo "Current User: $USER"
cecho "\033[31mPlease use the root user (do not use sudo directly!) to install!\033[0m"
echo "-----------------------------------------------"
read -p "Install anyway? Unknown errors may occur! (1/0) > " res
[ "$res" != "1" ] && exit 1
fi
}
check_version() {
echo "$url" | grep -q 'master' && setversion
webget /tmp/version "$url/version" echooff
[ "$result" = "200" ] && versionsh=$(cat /tmp/version)
rm -rf /tmp/version
# Output
cecho "Latest Version: \033[32m$versionsh\033[0m"
echo "-----------------------------------------------"
cecho "\033[44mFor issues, please join the TG group: \033[42;30m t.me/ShellClash \033[0m"
cecho "\033[37mSupports various OpenWrt-based router devices"
cecho "\033[33mSupports Debian, Centos and standard Linux systems\033[0m"
}
check_dir() {
if [ -n "$CRASHDIR" ]; then
echo "-----------------------------------------------"
cecho "Old installation detected at \033[36m$CRASHDIR\033[0m. Overwrite?"
cecho "\033[32mConfiguration files will NOT be removed during overwrite!\033[0m"
echo " 1 Overwrite Installation"
echo " 2 Uninstall old version and reinstall"
echo " 0 Cancel"
read -p "Enter number > " num
case "$num" in
1)
install
;;
2)
[ "$CRASHDIR" != "/" ] && rm -rf "$CRASHDIR"
echo "-----------------------------------------------"
cecho "\033[31mOld version uninstalled!\033[0m"
setdir
install
;;
9)
echo "Test Mode: Changing installation path $CRASHDIR"
setdir
install
;;
*)
cecho "\033[31mInstallation cancelled!\033[0m"
exit 1
;;
esac
else
setdir
install
fi
}
check_systype
check_user
check_version
check_dir

View File

@@ -72,6 +72,7 @@ localhost.ptlogin2.qq.com
localhost.sec.qq.com
#微信登录
localhost.*.weixin.qq.com
+.kk-rays.com
#Game
#Steam
+.steamcontent.com
@@ -154,4 +155,6 @@ ps.res.netease.com
+.orayimg.com
#LOL语音
+.gcloudcs.com
+.gcloudsdk.com
+.gcloudsdk.com
#ddns
+.dynv6.net

View File

@@ -3,9 +3,9 @@
101#$CRASHDIR/start.sh start#启动ShellCrash服务
102#$CRASHDIR/start.sh stop#停止ShellCrash服务
103#$CRASHDIR/start.sh restart#重启ShellCrash服务
104#$CRASHDIR/start.sh update_config#更新在线订阅并重启服务
105#$CRASHDIR/start.sh hotupdate#热更新在线订阅(不重启)
106#$CRASHDIR/start.sh web_save#自动保存面板配置
104#$CRASHDIR/task/task.sh update_config#更新在线订阅并重启服务
105#$CRASHDIR/task/task.sh hotupdate#热更新在线订阅(不重启)
106#$CRASHDIR/task/task.sh web_save_auto#自动保存面板配置
107#$CRASHDIR/task/task.sh ntp#自动同步ntp时间
111#$CRASHDIR/task/task.sh update_core#自动更新内核

View File

@@ -8,6 +8,8 @@ proxy-groups:
- {name: 🪟 微软服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- {name: 🇬 谷歌服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- {name: 🍎 苹果服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- {name: 🎥 奈飞视频, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 📹 油管视频, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 🌍 国外媒体, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 🎮 游戏平台, type: select, proxies: [🚀 节点选择, 🎯 全球直连, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 🛡️ 直连域名, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}

View File

@@ -7,6 +7,8 @@ proxy-groups:
- {name: 🎮 游戏服务, type: select, proxies: [🎯 全球直连, 👑 高级节点, 🚀 节点选择]}
- {name: 🪟 微软服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- {name: 🇬 谷歌服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- {name: 🎥 奈飞视频, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 📹 油管视频, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 🌍 国外媒体, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 🎮 游戏平台, type: select, proxies: [🚀 节点选择, 🎯 全球直连, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 🍎 苹果服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
@@ -77,6 +79,22 @@ rule-providers:
url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/games-cn.mrs"
interval: 86400
netflix:
type: http
behavior: domain
format: mrs
path: ./ruleset/netflix.mrs
url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/netflix.mrs"
interval: 86400
youtube:
type: http
behavior: domain
format: mrs
path: ./ruleset/youtube.mrs
url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/youtube.mrs"
interval: 86400
media:
type: http
behavior: domain
@@ -141,6 +159,14 @@ rule-providers:
url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cnip.mrs"
interval: 86400
netflixip:
type: http
behavior: domain
format: mrs
path: ./ruleset/netflixip.mrs
url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/netflixip.mrs"
interval: 86400
mediaip:
type: http
behavior: ipcidr
@@ -172,6 +198,8 @@ rules:
- RULE-SET,apple-cn,🍎 苹果服务
- RULE-SET,google-cn,🇬 谷歌服务
- RULE-SET,games-cn,🎮 游戏服务
- RULE-SET,netflix,🎥 奈飞视频
- RULE-SET,youtube,📹 油管视频
- RULE-SET,media,🌍 国外媒体
- RULE-SET,games,🎮 游戏平台
- RULE-SET,ai,🤖 AI 平台
@@ -180,6 +208,7 @@ rules:
- RULE-SET,cn,🛡️ 直连域名
- RULE-SET,privateip,🔒 私有网络,no-resolve
- RULE-SET,cnip,🀄️ 直连 IP
- RULE-SET,netflixip,🎥 奈飞视频
- RULE-SET,mediaip,🌍 国外媒体
- RULE-SET,gamesip,🎮 游戏平台
- RULE-SET,telegramip,📲 电报消息,no-resolve

View File

@@ -1,4 +1,4 @@
#ShellCrash-ruleset全分组规则+去广告
#ShellCrash-ruleset 全分组规则+去广告 For mihomo By Maozai 260111
#此版本为Maozai根据ACL4SSR规则修改优化而来尽量在保持原有的基础上进行优化。
#数据源采用了DustinWin/ruleset_geodata和MetaCubeX/meta-rules-dat两个开源项目的规则感谢原作者的辛勤付出。
@@ -8,49 +8,52 @@
#代理组
proxy-groups:
- { name: 🚀 节点选择, type: select, proxies: [♻️ 自动选择, ✨ 自动选择(去高倍率), 🛠️ 手动切换, ⚖️ 负载均衡, 🚑 故障转移, 🎯 全球直连, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- { name: 🛠️ 手动切换, type: select, include-all: true, exclude-type: direct }
- { name: ♻️ 自动选择, type: url-test, interval: 600, tolerance: 50, include-all: true, exclude-type: direct }
- { name: ✨ 自动选择(去高倍率), type: url-test, interval: 600, tolerance: 50, include-all: true, exclude-type: direct, filter: "(?i)^(?!.*(专线|专用|高级|高速|高倍率|IEPL|IPLC|x([2-9]|\\d{2,}))).*" }
- { name: ⚖️ 负载均衡, type: load-balance, interval: 600, include-all: true, exclude-type: direct, hidden: true }
- { name: 🚑 故障转移, type: fallback, interval: 600, include-all: true, exclude-type: direct, hidden: true }
- {name: 🚀 节点选择, type: select, proxies: [♻️ 自动选择, ✨ 自动选择(去高倍率), 🛠️ 手动切换, ⚖️ 负载均衡, 🚑 故障转移, 🎯 本地直连, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 🛠️ 手动切换, type: select, include-all: true, proxies: [🎯 本地直连, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: ♻️ 自动选择, type: url-test, interval: 1800, tolerance: 50, include-all: true, exclude-filter: "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www)"}
- {name: ✨ 自动选择(去高倍率), type: url-test, interval: 1800, tolerance: 50, include-all: true, exclude-filter: "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www)`(?i)(专线|专用|高级|直连|急速|高速|高倍率|游戏|铂金|钻石|企业|VIP|Ultra|Game|IEPL|IPLC|AIA|BGP|GIA|CN2|CMI|HGC|HKT|CTM|CC|AC|x([2-9]|\\d{2,}))"}
- {name: ⚖️ 负载均衡, type: load-balance, interval: 1800, include-all: true, hidden: true, exclude-filter: "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www)"}
- {name: 🚑 故障转移, type: fallback, interval: 1800, include-all: true, hidden: true, exclude-filter: "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www)"}
#
- {name: 🤖 AI 平台, type: select, proxies: [🚀 节点选择, 🤖 AI节点过滤港澳, 🎯 本地直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 🤖 AI节点过滤港澳, type: url-test, interval: 3600, tolerance: 50, include-all: true, exclude-filter: "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www)`(?i)(🇭🇰|港|🇲🇴|澳门|hk|hongkong|hong kong)", hidden: true}
- {name: 🎬 奈飞视频, type: select, proxies: [🚀 节点选择, 🎬 奈飞节点, 🎯 本地直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 🎬 奈飞节点, type: url-test, interval: 1800, tolerance: 50, include-all: true, filter: "(?i)(NF|奈飞|解锁|Netflix|NETFLIX|Media)", hidden: true}
- {name: ▶️ 油管视频, type: select, proxies: [🚀 节点选择, 🎯 本地直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 📢 谷歌推送, type: select, proxies: [🚀 节点选择, 🎯 本地直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 📲 电报消息, type: select, proxies: [🚀 节点选择, 🎯 本地直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 🌍 国际媒体, type: select, proxies: [🚀 节点选择, 🎯 本地直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 🌐 国际流量, type: select, proxies: [🚀 节点选择, 🎯 本地直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 🎮 外服游戏, type: select, proxies: [🚀 节点选择, 🎯 本地直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- { name: 🤖 AI 平台, type: select, proxies: [🚀 节点选择, 🤖 AI节点过滤港澳, 🎯 全球直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- { name: 🤖 AI节点过滤港澳, type: url-test, interval: 1800, tolerance: 50, include-all: true, filter: "(?i)^(?!.*(🇭🇰|港|🇲🇴|澳门|hk|hongkong|hong kong)).*", hidden: true }
- { name: 📢 谷歌FCM, type: select, proxies: [🚀 节点选择, 🎯 全球直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- { name: 🎥 奈飞视频, type: select, proxies: [🚀 节点选择, 🎥 奈飞节点, 🎯 全球直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- { name: 🎥 奈飞节点, type: url-test, interval: 1800, tolerance: 50, include-all: true, filter: "(?i)(NF|奈飞|解锁|Netflix|NETFLIX|Media)", hidden: true }
- { name: 📹 油管视频, type: select, proxies: [🚀 节点选择, 🎯 全球直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- { name: 📲 电报消息, type: select, proxies: [🚀 节点选择, 🎯 全球直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- { name: 🌍 国外媒体, type: select, proxies: [🚀 节点选择, 🎯 全球直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- { name: 🧱 代理域名, type: select, proxies: [🚀 节点选择, 🎯 全球直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- { name: 🎮 国外游戏, type: select, proxies: [🚀 节点选择, 🎯 全球直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- {name: 🕹 国服游戏, type: select, proxies: [🎯 本地直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, {providers_tags}]}
- {name: 🦾 Steam平台, type: select, proxies: [🎯 本地直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 🪟 微软服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 🍎 苹果服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 🇬 谷歌服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 🧲 BT下载, type: select, proxies: [🎯 本地直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 📈 网络测速, type: select, proxies: [🎯 本地直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: ↔️ 直连软件, type: select, proxies: [🎯 本地直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, {providers_tags}]}
- {name: 🀄️ 国内流量, type: select, proxies: [🎯 本地直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, {providers_tags}]}
- { name: 🕹 国内游戏, type: select, proxies: [🎯 全球直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, {providers_tags}] }
- { name: 🪟 微软服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- { name: 🍎 苹果服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- { name: 💾 trackerslist, type: select, proxies: [🎯 全球直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- { name: 📈 网络测试, type: select, proxies: [🎯 全球直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- { name: ↔️ 国外直连, type: select, proxies: [🎯 全球直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- { name: 🀄️ 国内直连, type: select, proxies: [🎯 全球直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, {providers_tags}] }
- {name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🎯 本地直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- { name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🎯 全球直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- {name: 🛑 广告拦截, type: select, proxies: [🔴 拦截, 🟢 放行]}
- {name: 🔒 私有网络, type: select, proxies: [DIRECT], hidden: true}
- {name: 🔴 拦截, type: select, proxies: [REJECT], hidden: true}
- {name: 🟢 放行, type: select, proxies: [PASS], hidden: true}
- {name: 🎯 本地直连, type: select, proxies: [DIRECT], hidden: true}
- { name: 🛑 广告拦截, type: select, proxies: [🔴 全球拦截, 🎯 全球直连] }
- { name: 🔒 私有网络, type: select, proxies: [DIRECT], hidden: true }
- { name: 🔴 全球拦截, type: select, proxies: [REJECT], hidden: true }
- { name: 🎯 全球直连, type: select, proxies: [DIRECT], hidden: true }
- {name: 🇭🇰 香港节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇭🇰|港|hk|hongkong|hong kong)"}
- {name: 🇹🇼 台湾节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇹🇼|台|tw|taiwan|tai wan)", exclude-filter: "(?i)(仙台)"}
- {name: 🇺🇸 美国节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇺🇸|美|洛杉矶|圣何塞|西雅图|纽约|波特兰|旧金山|休斯|达拉斯|硅谷|堪萨斯|迈阿密|凤凰城|芝加哥|奥勒姆|us|unitedstates|united states)", exclude-filter: "(?i)(南美|中美|拉美|亚美尼亚|美属)"}
- {name: 🇯🇵 日本节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇯🇵|日|东京|大阪|埼玉|九州|仙台|jp|japan)", exclude-filter: "(?i)(尼日利亚|尼日尔|日内瓦)"}
- {name: 🇪🇺 欧洲节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇪🇺|欧|德|英|法|荷|俄罗斯|西班牙|意大利|瑞士|瑞典|土耳其|挪威|芬兰|丹麦|比利时|爱尔兰|奥地利|波兰|葡萄牙|乌克兰|希腊|捷克|匈牙利|罗马尼亚|保加利亚|冰岛|克罗地亚|阿姆斯特丹)"}
- {name: 🇰🇷 韩国节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇰🇷|韩|韓|首尔|kr|kor)"}
- {name: 🇸🇬 狮城节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇸🇬|新加坡|狮城|sg|singapore)"}
- { name: 🇭🇰 香港节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇭🇰|港|hk|hongkong|hong kong)" }
- { name: 🇹🇼 台湾节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇹🇼|台|tw|taiwan|tai wan)" }
- { name: 🇸🇬 狮城节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇸🇬|新|坡|狮城|sg|singapore)" }
- { name: 🇯🇵 日本节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇯🇵|日|东京|大阪|泉日|埼玉|jp|japan)" }
- { name: 🇰🇷 韩国节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(KR|首尔|韩|韓|kor)" }
- { name: 🇺🇸 美国节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇺🇸|美|us|unitedstates|united states)" }
- { name: 🇪🇺 欧洲节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇪🇺|欧|欧洲|eu|eur|德|英|瑞|法|荷|土耳|意大利|西班牙)" }
- { name: 👑 高级节点, type: url-test, interval: 1800, tolerance: 50, include-all: true, filter: "(?i)(专线|专用|高级|直连|急速|高速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)" }
- { name: 📉 省流节点, type: url-test, interval: 1800, tolerance: 50, include-all: true, filter: "(0\\.[1-6]|低倍率|省流|大流量)" }
- {name: 👑 高级节点, type: url-test, interval: 1800, tolerance: 50, include-all: true, filter: "(?i)(专线|专用|高级|直连|急速|高速|高倍率|游戏|铂金|钻石|企业|VIP|Ultra|Game|IEPL|IPLC|AIA|BGP|GIA|CN2|CMI|HGC|HKT|CTM|CC|AC|x([2-9]|\\d{2,}))"}
- {name: 📉 省流节点, type: url-test, interval: 1800, tolerance: 50, include-all: true, filter: "(?i)(0\\.[1-6]|低倍率|省流|大流量|公益|免费|闲时|Low)"}
#规则提供者更新mrs格式
rule-providers:
@@ -59,185 +62,193 @@ rule-providers:
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/ai.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/ai.mrs"
youtube:
type: http
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/youtube.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/youtube.mrs"
netflix:
type: http
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/netflix.mrs"
telegram:
type: http
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@refs/heads/meta/geo/geosite/telegram.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/netflix.mrs"
telegramip:
type: http
format: mrs
interval: 86400
behavior: ipcidr
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/telegramip.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/telegramip.mrs"
trackerslist:
type: http
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/trackerslist.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/trackerslist.mrs"
applications:
type: http
format: text
interval: 86400
behavior: classical
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/applications.list"
private:
type: http
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/private.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/private.mrs"
privateip:
type: http
format: mrs
interval: 86400
behavior: ipcidr
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/privateip.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/privateip.mrs"
networktest:
type: http
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/networktest.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/networktest.mrs"
apple-cn:
type: http
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/apple-cn.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/apple-cn.mrs"
google-cn:
type: http
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/google-cn.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/google-cn.mrs"
googlefcm:
type: http
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@refs/heads/meta/geo/geosite/googlefcm.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@refs/heads/meta/geo/geosite/googlefcm.mrs"
steamcn:
type: http
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@refs/heads/meta/geo/geosite/steam@cn.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@refs/heads/meta/geo/geosite/steam@cn.mrs"
microsoft-cn:
type: http
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/microsoft-cn.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/microsoft-cn.mrs"
games-cn:
type: http
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/games-cn.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/games-cn.mrs"
games:
type: http
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/games.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/games.mrs"
gamesip:
type: http
format: mrs
interval: 86400
behavior: ipcidr
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/gamesip.mrs"
tld-proxy:
type: http
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/tld-proxy.mrs"
cn-lite:
type: http
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cn-lite.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/gamesip.mrs"
mediaip:
type: http
format: mrs
interval: 86400
behavior: ipcidr
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/mediaip.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/mediaip.mrs"
media:
type: http
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/media.mrs"
gfw:
type: http
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/gfw.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/media.mrs"
cnip:
type: http
format: mrs
interval: 86400
behavior: ipcidr
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cnip.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cnip.mrs"
proxy:
type: http
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/proxy.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/proxy.mrs"
cn:
type: http
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cn.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cn.mrs"
ads:
type: http
format: mrs
interval: 86400
behavior: domain
url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/ads.mrs"
proxy: DIRECT
url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/ads.mrs"
#规则顺序
rules:
- DOMAIN-SUFFIX,captive.apple.com,🍎 苹果服务
- DOMAIN-SUFFIX,kamo.teracloud.jp,🀄️ 国内流量
- RULE-SET,privateip,🔒 私有网络,no-resolve
- RULE-SET,private,🔒 私有网络
- RULE-SET,ads,🛑 广告拦截
- RULE-SET,networktest,📈 网络测试
- RULE-SET,trackerslist,💾 trackerslist
- RULE-SET,googlefcm,📢 谷歌FCM
- RULE-SET,google-cn,↔️ 国外直连
- RULE-SET,steamcn,↔️ 国外直连
- RULE-SET,microsoft-cn,🪟 微软服务
- RULE-SET,apple-cn,🍎 苹果服务
- RULE-SET,telegramip,📲 电报消息,no-resolve
- RULE-SET,telegram,📲 电报消息
- RULE-SET,netflix,🎥 奈飞视频
- RULE-SET,youtube,📹 油管视频
- RULE-SET,ai,🤖 AI 平台
- RULE-SET,ads,🛑 广告拦截
- RULE-SET,networktest,📈 网络测速
- RULE-SET,applications,↔️ 直连软件
- RULE-SET,trackerslist,🧲 BT下载
- RULE-SET,apple-cn,🍎 苹果服务
- RULE-SET,microsoft-cn,🪟 微软服务
- RULE-SET,google-cn,🇬 谷歌服务
- RULE-SET,steamcn,🦾 Steam平台
- RULE-SET,games-cn,🕹 国服游戏
- RULE-SET,googlefcm,📢 谷歌推送
- RULE-SET,netflix,🎬 奈飞视频
- RULE-SET,youtube,▶️ 油管视频
- RULE-SET,ai,🤖 AI 平台
- RULE-SET,media,🌍 国际媒体
- RULE-SET,games,🎮 外服游戏
- RULE-SET,proxy,🌐 国际流量
- RULE-SET,cn,🀄️ 国内流量
- RULE-SET,gamesip,🎮 外服游戏
- RULE-SET,mediaip,🌍 国际媒体
- RULE-SET,cnip,🀄️ 国内流量
- RULE-SET,games-cn,🕹 国内游戏
- RULE-SET,gamesip,🎮 国外游戏
- RULE-SET,games,🎮 国外游戏
- RULE-SET,mediaip,🌍 国外媒体
- RULE-SET,media,🌍 国外媒体
- RULE-SET,tld-proxy,🧱 代理域名
- RULE-SET,cn-lite,🀄️ 国内直连
- RULE-SET,gfw,🧱 代理域名
- RULE-SET,cnip,🀄️ 国内直连
- RULE-SET,proxy,🧱 代理域名
- RULE-SET,cn,🀄️ 国内直连
- MATCH,🐟 漏网之鱼

View File

@@ -1,4 +1,5 @@
ShellCrash-ruleset极简规则 ShellCrash_RS_Nano.yaml
ShellCrash-ruleset全分组规则+去广告 ShellCrash_RS_Full_BanAds.yaml
DustinWin-ruleset轻量规则 DustinWin_RS_Light.yaml
DustinWin-ruleset标准规则 DustinWin_RS_Lite_NoAds.yaml
DustinWin-ruleset标准规则+去广告 DustinWin_RS_Lite.yaml

View File

@@ -1,23 +1,27 @@
//DustinWin-ruleset全分组规则+去广告
{
"outbounds": [
{ "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 全球直连", {providers_tags} ] },
{ "tag": "📈 网络测试", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 本地直连", {providers_tags} ] },
{ "tag": "📈 网络测试", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🤖 AI 平台", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点" ] },
{ "tag": "📋 Trackerslist", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🎮 游戏服务", "type": "selector", "outbounds": [ "🎯 全球直连", "👑 高级节点", "🚀 节点选择" ] },
{ "tag": "🪟 微软服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🇬 谷歌服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🍎 苹果服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "📋 Trackerslist", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🎮 游戏服务", "type": "selector", "outbounds": [ "🎯 本地直连", "👑 高级节点", "🚀 节点选择" ] },
{ "tag": "🪟 微软服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🇬 谷歌服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🍎 苹果服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🎥 奈飞视频", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "📹 油管视频", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🌍 国外媒体", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🎮 游戏平台", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 全球直连", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🛡️ 直连域名", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🀄️ 直连 IP", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🧱 代理域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 全球直连" ] },
{ "tag": "🎮 游戏平台", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🛡️ 直连域名", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🀄️ 直连 IP", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🧱 代理域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
{ "tag": "📲 电报消息", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 全球直连" ] },
{ "tag": "🎯 全球直连", "type": "selector", "outbounds": [ "DIRECT" ] },
{ "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "DIRECT" ] },
{ "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 本地直连" ] },
{ "tag": "🛑 广告域名", "type": "selector", "outbounds": [ "🔴 全球拦截", "🎯 本地直连" ] },
{ "tag": "🔴 全球拦截", "type": "block" },
{ "tag": "🎯 本地直连", "type": "direct" },
{ "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
{ "tag": "👑 高级节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(专线|专用|高级|直连|急速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)" },
{ "tag": "📉 省流节点", "type": "urltest", "tolerance": 100, "use_all_providers": true, "include": "0\\.[1-5]|低倍率|省流|大流量" },
{ "tag": "♻️ 自动选择", "type": "urltest", "tolerance": 100, "use_all_providers": true },
@@ -30,24 +34,27 @@
],
"route": {
"rules": [
{ "rule_set": [ "private" ], "outbound": "🎯 全球直连" },
{ "rule_set": [ "ads" ], "action": "reject" },
{ "rule_set": [ "private" ], "outbound": "🎯 本地直连" },
{ "rule_set": [ "ads" ], "outbound": "🛑 广告域名" },
{ "rule_set": [ "trackerslist" ], "outbound": "📋 Trackerslist" },
{ "rule_set": [ "microsoft-cn" ], "outbound": "🪟 微软服务" },
{ "rule_set": [ "apple-cn" ], "outbound": "🍎 苹果服务" },
{ "rule_set": [ "google-cn" ], "outbound": "🇬 谷歌服务" },
{ "rule_set": [ "games-cn" ], "outbound": "🎮 游戏服务" },
{ "rule_set": [ "netflix" ], "outbound": "🎥 奈飞视频" },
{ "rule_set": [ "youtube" ], "outbound": "📹 油管视频" },
{ "rule_set": [ "media" ], "outbound": "🌍 国外媒体" },
{ "rule_set": [ "games" ], "outbound": "🎮 游戏平台" },
{ "rule_set": [ "ai" ], "outbound": "🤖 AI 平台" },
{ "rule_set": [ "networktest" ], "outbound": "📈 网络测试" },
{ "rule_set": [ "proxy" ], "outbound": "🧱 代理域名" },
{ "rule_set": [ "cn" ], "outbound": "🛡️ 直连域名" },
{ "rule_set": [ "privateip" ], "outbound": "🎯 全球直连" },
{ "rule_set": [ "privateip" ], "outbound": "🎯 本地直连" },
{ "rule_set": [ "telegramip" ], "outbound": "📲 电报消息" },
{ "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4"},
{ "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4", "match_only": true},
{ "rule_set": [ "cnip" ], "outbound": "🀄️ 直连 IP" },
{ "rule_set": [ "netflixip" ], "outbound": "🎥 奈飞视频" },
{ "rule_set": [ "mediaip" ], "outbound": "🌍 国外媒体" },
{ "rule_set": [ "gamesip" ], "outbound": "🎮 游戏平台" }
],
@@ -57,126 +64,168 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/private.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs",
"download_detour": "DIRECT"
},
{
"tag": "ads",
"type": "remote",
"format": "binary",
"path": "./ruleset/ads.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ads.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ads.srs",
"download_detour": "DIRECT"
},
{
"tag": "trackerslist",
"type": "remote",
"format": "binary",
"path": "./ruleset/trackerslist.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/trackerslist.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/trackerslist.srs",
"download_detour": "DIRECT"
},
{
"tag": "microsoft-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/microsoft-cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/microsoft-cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/microsoft-cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "apple-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/apple-cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/apple-cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/apple-cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "google-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/google-cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/google-cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/google-cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "games-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/games-cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games-cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games-cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "netflix",
"type": "remote",
"format": "binary",
"path": "./ruleset/netflix.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/netflix.srs",
"download_detour": "DIRECT"
},
{
"tag": "youtube",
"type": "remote",
"format": "binary",
"path": "./ruleset/youtube.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/youtube.srs",
"download_detour": "DIRECT"
},
{
"tag": "media",
"type": "remote",
"format": "binary",
"path": "./ruleset/media.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/media.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/media.srs",
"download_detour": "DIRECT"
},
{
"tag": "games",
"type": "remote",
"format": "binary",
"path": "./ruleset/games.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games.srs",
"download_detour": "DIRECT"
},
{
"tag": "ai",
"type": "remote",
"format": "binary",
"path": "./ruleset/ai.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ai.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ai.srs",
"download_detour": "DIRECT"
},
{
"tag": "networktest",
"type": "remote",
"format": "binary",
"path": "./ruleset/networktest.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/networktest.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/networktest.srs",
"download_detour": "DIRECT"
},
{
"tag": "proxy",
"type": "remote",
"format": "binary",
"path": "./ruleset/proxy.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs",
"download_detour": "DIRECT"
},
{
"tag": "cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "privateip",
"type": "remote",
"format": "binary",
"path": "./ruleset/privateip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs",
"download_detour": "DIRECT"
},
{
"tag": "cnip",
"type": "remote",
"format": "binary",
"path": "./ruleset/cnip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs",
"download_detour": "DIRECT"
},
{
"tag": "netflixip",
"type": "remote",
"format": "binary",
"path": "./ruleset/netflixip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/netflixip.srs",
"download_detour": "DIRECT"
},
{
"tag": "mediaip",
"type": "remote",
"format": "binary",
"path": "./ruleset/mediaip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/mediaip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/mediaip.srs",
"download_detour": "DIRECT"
},
{
"tag": "gamesip",
"type": "remote",
"format": "binary",
"path": "./ruleset/gamesip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/gamesip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/gamesip.srs",
"download_detour": "DIRECT"
},
{
"tag": "telegramip",
"type": "remote",
"format": "binary",
"path": "./ruleset/telegramip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs",
"download_detour": "DIRECT"
}
],
"final": "🐟 漏网之鱼"

View File

@@ -1,23 +1,25 @@
//DustinWin-ruleset全分组规则
{
"outbounds": [
{ "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 全球直连", {providers_tags} ] },
{ "tag": "📈 网络测试", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 本地直连", {providers_tags} ] },
{ "tag": "📈 网络测试", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🤖 AI 平台", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点" ] },
{ "tag": "📋 Trackerslist", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🎮 游戏服务", "type": "selector", "outbounds": [ "🎯 全球直连", "👑 高级节点", "🚀 节点选择" ] },
{ "tag": "🪟 微软服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🇬 谷歌服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🍎 苹果服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "📋 Trackerslist", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🎮 游戏服务", "type": "selector", "outbounds": [ "🎯 本地直连", "👑 高级节点", "🚀 节点选择" ] },
{ "tag": "🪟 微软服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🇬 谷歌服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🍎 苹果服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🎥 奈飞视频", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "📹 油管视频", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🌍 国外媒体", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🎮 游戏平台", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 全球直连", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🛡️ 直连域名", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🀄️ 直连 IP", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🧱 代理域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 全球直连" ] },
{ "tag": "🎮 游戏平台", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🛡️ 直连域名", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🀄️ 直连 IP", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🧱 代理域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
{ "tag": "📲 电报消息", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 全球直连" ] },
{ "tag": "🎯 全球直连", "type": "selector", "outbounds": [ "DIRECT" ] },
{ "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "DIRECT" ] },
{ "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 本地直连" ] },
{ "tag": "🎯 本地直连", "type": "direct" },
{ "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
{ "tag": "👑 高级节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(专线|专用|高级|直连|急速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)" },
{ "tag": "📉 省流节点", "type": "urltest", "tolerance": 100, "use_all_providers": true, "include": "0\\.[1-5]|低倍率|省流|大流量" },
{ "tag": "♻️ 自动选择", "type": "urltest", "tolerance": 100, "use_all_providers": true },
@@ -30,23 +32,26 @@
],
"route": {
"rules": [
{ "rule_set": [ "private" ], "outbound": "🎯 全球直连" },
{ "rule_set": [ "private" ], "outbound": "🎯 本地直连" },
{ "rule_set": [ "trackerslist" ], "outbound": "📋 Trackerslist" },
{ "rule_set": [ "microsoft-cn" ], "outbound": "🪟 微软服务" },
{ "rule_set": [ "apple-cn" ], "outbound": "🍎 苹果服务" },
{ "rule_set": [ "google-cn" ], "outbound": "🇬 谷歌服务" },
{ "rule_set": [ "games-cn" ], "outbound": "🎮 游戏服务" },
{ "rule_set": [ "netflix" ], "outbound": "🎥 奈飞视频" },
{ "rule_set": [ "youtube" ], "outbound": "📹 油管视频" },
{ "rule_set": [ "media" ], "outbound": "🌍 国外媒体" },
{ "rule_set": [ "games" ], "outbound": "🎮 游戏平台" },
{ "rule_set": [ "ai" ], "outbound": "🤖 AI 平台" },
{ "rule_set": [ "networktest" ], "outbound": "📈 网络测试" },
{ "rule_set": [ "proxy" ], "outbound": "🧱 代理域名" },
{ "rule_set": [ "cn" ], "outbound": "🛡️ 直连域名" },
{ "rule_set": [ "privateip" ], "outbound": "🎯 全球直连" },
{ "rule_set": [ "privateip" ], "outbound": "🎯 本地直连" },
{ "rule_set": [ "telegramip" ], "outbound": "📲 电报消息" },
{ "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4"},
{ "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4", "match_only": true},
{ "rule_set": [ "cnip" ], "outbound": "🀄️ 直连 IP" },
{ "rule_set": [ "netflixip" ], "outbound": "🎥 奈飞视频" },
{ "rule_set": [ "mediaip" ], "outbound": "🌍 国外媒体" },
{ "rule_set": [ "gamesip" ], "outbound": "🎮 游戏平台" }
],
@@ -56,119 +61,160 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/private.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs",
"download_detour": "DIRECT"
},
{
"tag": "trackerslist",
"type": "remote",
"format": "binary",
"path": "./ruleset/trackerslist.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/trackerslist.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/trackerslist.srs",
"download_detour": "DIRECT"
},
{
"tag": "microsoft-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/microsoft-cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/microsoft-cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/microsoft-cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "apple-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/apple-cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/apple-cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/apple-cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "google-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/google-cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/google-cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/google-cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "games-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/games-cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games-cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games-cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "netflix",
"type": "remote",
"format": "binary",
"path": "./ruleset/netflix.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/netflix.srs",
"download_detour": "DIRECT"
},
{
"tag": "youtube",
"type": "remote",
"format": "binary",
"path": "./ruleset/youtube.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/youtube.srs",
"download_detour": "DIRECT"
},
{
"tag": "media",
"type": "remote",
"format": "binary",
"path": "./ruleset/media.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/media.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/media.srs",
"download_detour": "DIRECT"
},
{
"tag": "games",
"type": "remote",
"format": "binary",
"path": "./ruleset/games.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games.srs",
"download_detour": "DIRECT"
},
{
"tag": "ai",
"type": "remote",
"format": "binary",
"path": "./ruleset/ai.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ai.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ai.srs",
"download_detour": "DIRECT"
},
{
"tag": "networktest",
"type": "remote",
"format": "binary",
"path": "./ruleset/networktest.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/networktest.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/networktest.srs",
"download_detour": "DIRECT"
},
{
"tag": "proxy",
"type": "remote",
"format": "binary",
"path": "./ruleset/proxy.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs",
"download_detour": "DIRECT"
},
{
"tag": "cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "privateip",
"type": "remote",
"format": "binary",
"path": "./ruleset/privateip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs",
"download_detour": "DIRECT"
},
{
"tag": "cnip",
"type": "remote",
"format": "binary",
"path": "./ruleset/cnip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs",
"download_detour": "DIRECT"
},
{
"tag": "netflixip",
"type": "remote",
"format": "binary",
"path": "./ruleset/netflixip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/netflixip.srs",
"download_detour": "DIRECT"
},
{
"tag": "mediaip",
"type": "remote",
"format": "binary",
"path": "./ruleset/mediaip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/mediaip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/mediaip.srs",
"download_detour": "DIRECT"
},
{
"tag": "gamesip",
"type": "remote",
"format": "binary",
"path": "./ruleset/gamesip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/gamesip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/gamesip.srs",
"download_detour": "DIRECT"
},
{
"tag": "telegramip",
"type": "remote",
"format": "binary",
"path": "./ruleset/telegramip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs",
"download_detour": "DIRECT"
}
],
"final": "🐟 漏网之鱼"

View File

@@ -1,12 +1,12 @@
//DustinWin-ruleset轻量规则
{
"outbounds": [
{ "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 全球直连", {providers_tags} ] },
{ "tag": "🧱 代理域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 全球直连" ] },
{ "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 本地直连", {providers_tags} ] },
{ "tag": "🧱 代理域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
{ "tag": "📲 电报消息", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 全球直连" ] },
{ "tag": "🎯 全球直连", "type": "selector", "outbounds": [ "DIRECT" ] },
{ "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "DIRECT" ] },
{ "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 本地直连" ] },
{ "tag": "🎯 本地直连", "type": "direct" },
{ "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
{ "tag": "👑 高级节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(专线|专用|高级|直连|急速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)" },
{ "tag": "📉 省流节点", "type": "urltest", "tolerance": 100, "use_all_providers": true, "include": "0\\.[1-5]|低倍率|省流|大流量" },
{ "tag": "♻️ 自动选择", "type": "urltest", "tolerance": 100, "use_all_providers": true },
@@ -19,15 +19,15 @@
],
"route": {
"rules": [
{ "rule_set": [ "private" ], "outbound": "🎯 全球直连" },
{ "rule_set": [ "private" ], "outbound": "🎯 本地直连" },
{ "rule_set": [ "tld-proxy" ], "outbound": "🧱 代理域名" },
{ "rule_set": [ "proxy" ], "outbound": "🧱 代理域名" },
{ "rule_set": [ "cn" ], "outbound": "🎯 全球直连" },
{ "rule_set": [ "privateip" ], "outbound": "🎯 全球直连" },
{ "rule_set": [ "cn" ], "outbound": "🎯 本地直连" },
{ "rule_set": [ "privateip" ], "outbound": "🎯 本地直连" },
{ "rule_set": [ "telegramip" ], "outbound": "📲 电报消息" },
{ "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4"},
{ "rule_set": [ "cnip" ], "outbound": "🎯 全球直连" }
{ "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4", "match_only": true},
{ "rule_set": [ "cnip" ], "outbound": "🎯 本地直连" }
],
"rule_set": [
{
@@ -35,49 +35,56 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "private",
"type": "remote",
"format": "binary",
"path": "./ruleset/private.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs",
"download_detour": "DIRECT"
},
{
"tag": "tld-proxy",
"type": "remote",
"format": "binary",
"path": "./ruleset/tld-proxy.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/tld-proxy.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/tld-proxy.srs",
"download_detour": "DIRECT"
},
{
"tag": "proxy",
"type": "remote",
"format": "binary",
"path": "./ruleset/proxy.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs",
"download_detour": "DIRECT"
},
{
"tag": "privateip",
"type": "remote",
"format": "binary",
"path": "./ruleset/privateip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs",
"download_detour": "DIRECT"
},
{
"tag": "cnip",
"type": "remote",
"format": "binary",
"path": "./ruleset/cnip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs",
"download_detour": "DIRECT"
},
{
"tag": "telegramip",
"type": "remote",
"format": "binary",
"path": "./ruleset/telegramip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs",
"download_detour": "DIRECT"
}
],
"final": "🐟 漏网之鱼"

View File

@@ -1,21 +1,23 @@
//DustinWin-ruleset标准规则+去广告
{
"outbounds": [
{ "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 全球直连", {providers_tags} ] },
{ "tag": "📈 网络测试", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 本地直连", {providers_tags} ] },
{ "tag": "📈 网络测试", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🤖 AI 平台", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点" ] },
{ "tag": "📋 Trackerslist", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🎮 游戏服务", "type": "selector", "outbounds": [ "🎯 全球直连", "👑 高级节点", "🚀 节点选择" ] },
{ "tag": "🪟 微软服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🇬 谷歌服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🍎 苹果服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🛡️ 直连域名", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🀄️ 直连 IP", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🧱 代理域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 全球直连" ] },
{ "tag": "📋 Trackerslist", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🎮 游戏服务", "type": "selector", "outbounds": [ "🎯 本地直连", "👑 高级节点", "🚀 节点选择" ] },
{ "tag": "🪟 微软服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🇬 谷歌服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🍎 苹果服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🛡️ 直连域名", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🀄️ 直连 IP", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🧱 代理域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
{ "tag": "📲 电报消息", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 全球直连" ] },
{ "tag": "🎯 全球直连", "type": "selector", "outbounds": [ "DIRECT" ] },
{ "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "DIRECT" ] },
{ "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 本地直连" ] },
{ "tag": "🛑 广告域名", "type": "selector", "outbounds": [ "🔴 全球拦截", "🎯 本地直连" ] },
{ "tag": "🔴 全球拦截", "type": "block" },
{ "tag": "🎯 本地直连", "type": "direct" },
{ "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
{ "tag": "👑 高级节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(专线|专用|高级|直连|急速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)" },
{ "tag": "📉 省流节点", "type": "urltest", "tolerance": 100, "use_all_providers": true, "include": "0\\.[1-5]|低倍率|省流|大流量" },
{ "tag": "♻️ 自动选择", "type": "urltest", "tolerance": 100, "use_all_providers": true },
@@ -28,8 +30,8 @@
],
"route": {
"rules": [
{ "rule_set": [ "private" ], "outbound": "🎯 全球直连" },
{ "rule_set": [ "ads" ], "action": "reject" },
{ "rule_set": [ "private" ], "outbound": "🎯 本地直连" },
{ "rule_set": [ "ads" ], "outbound": "🛑 广告域名" },
{ "rule_set": [ "trackerslist" ], "outbound": "📋 Trackerslist" },
{ "rule_set": [ "microsoft-cn" ], "outbound": "🪟 微软服务" },
{ "rule_set": [ "apple-cn" ], "outbound": "🍎 苹果服务" },
@@ -39,10 +41,10 @@
{ "rule_set": [ "networktest" ], "outbound": "📈 网络测试" },
{ "rule_set": [ "proxy" ], "outbound": "🧱 代理域名" },
{ "rule_set": [ "cn" ], "outbound": "🛡️ 直连域名" },
{ "rule_set": [ "privateip" ], "outbound": "🎯 全球直连" },
{ "rule_set": [ "privateip" ], "outbound": "🎯 本地直连" },
{ "rule_set": [ "telegramip" ], "outbound": "📲 电报消息" },
{ "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4"},
{ "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4", "match_only": true},
{ "rule_set": [ "cnip" ], "outbound": "🀄️ 直连 IP" }
],
"rule_set": [
@@ -51,98 +53,112 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/private.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs",
"download_detour": "DIRECT"
},
{
"tag": "ads",
"type": "remote",
"format": "binary",
"path": "./ruleset/ads.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ads.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ads.srs",
"download_detour": "DIRECT"
},
{
"tag": "trackerslist",
"type": "remote",
"format": "binary",
"path": "./ruleset/trackerslist.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/trackerslist.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/trackerslist.srs",
"download_detour": "DIRECT"
},
{
"tag": "microsoft-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/microsoft-cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/microsoft-cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/microsoft-cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "apple-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/apple-cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/apple-cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/apple-cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "google-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/google-cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/google-cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/google-cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "games-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/games-cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games-cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games-cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "ai",
"type": "remote",
"format": "binary",
"path": "./ruleset/ai.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ai.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ai.srs",
"download_detour": "DIRECT"
},
{
"tag": "networktest",
"type": "remote",
"format": "binary",
"path": "./ruleset/networktest.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/networktest.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/networktest.srs",
"download_detour": "DIRECT"
},
{
"tag": "proxy",
"type": "remote",
"format": "binary",
"path": "./ruleset/proxy.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs",
"download_detour": "DIRECT"
},
{
"tag": "cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "privateip",
"type": "remote",
"format": "binary",
"path": "./ruleset/privateip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs",
"download_detour": "DIRECT"
},
{
"tag": "cnip",
"type": "remote",
"format": "binary",
"path": "./ruleset/cnip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs",
"download_detour": "DIRECT"
},
{
"tag": "telegramip",
"type": "remote",
"format": "binary",
"path": "./ruleset/telegramip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs",
"download_detour": "DIRECT"
}
],
"final": "🐟 漏网之鱼"

View File

@@ -1,21 +1,21 @@
//DustinWin-ruleset标准规则
{
"outbounds": [
{ "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 全球直连", {providers_tags} ] },
{ "tag": "📈 网络测试", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 本地直连", {providers_tags} ] },
{ "tag": "📈 网络测试", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🤖 AI 平台", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点" ] },
{ "tag": "📋 Trackerslist", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🎮 游戏服务", "type": "selector", "outbounds": [ "🎯 全球直连", "👑 高级节点", "🚀 节点选择" ] },
{ "tag": "🪟 微软服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🇬 谷歌服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🍎 苹果服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🛡️ 直连域名", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🀄️ 直连 IP", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
{ "tag": "🧱 代理域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 全球直连" ] },
{ "tag": "📋 Trackerslist", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🎮 游戏服务", "type": "selector", "outbounds": [ "🎯 本地直连", "👑 高级节点", "🚀 节点选择" ] },
{ "tag": "🪟 微软服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🇬 谷歌服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🍎 苹果服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🛡️ 直连域名", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🀄️ 直连 IP", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🧱 代理域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
{ "tag": "📲 电报消息", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 全球直连" ] },
{ "tag": "🎯 全球直连", "type": "selector", "outbounds": [ "DIRECT" ] },
{ "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "DIRECT" ] },
{ "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 本地直连" ] },
{ "tag": "🎯 本地直连", "type": "direct" },
{ "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
{ "tag": "👑 高级节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(专线|专用|高级|直连|急速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)" },
{ "tag": "📉 省流节点", "type": "urltest", "tolerance": 100, "use_all_providers": true, "include": "0\\.[1-5]|低倍率|省流|大流量" },
{ "tag": "♻️ 自动选择", "type": "urltest", "tolerance": 100, "use_all_providers": true },
@@ -28,7 +28,7 @@
],
"route": {
"rules": [
{ "rule_set": [ "private" ], "outbound": "🎯 全球直连" },
{ "rule_set": [ "private" ], "outbound": "🎯 本地直连" },
{ "rule_set": [ "trackerslist" ], "outbound": "📋 Trackerslist" },
{ "rule_set": [ "microsoft-cn" ], "outbound": "🪟 微软服务" },
{ "rule_set": [ "apple-cn" ], "outbound": "🍎 苹果服务" },
@@ -38,10 +38,10 @@
{ "rule_set": [ "networktest" ], "outbound": "📈 网络测试" },
{ "rule_set": [ "proxy" ], "outbound": "🧱 代理域名" },
{ "rule_set": [ "cn" ], "outbound": "🛡️ 直连域名" },
{ "rule_set": [ "privateip" ], "outbound": "🎯 全球直连" },
{ "rule_set": [ "privateip" ], "outbound": "🎯 本地直连" },
{ "rule_set": [ "telegramip" ], "outbound": "📲 电报消息" },
{ "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4"},
{ "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4", "match_only": true},
{ "rule_set": [ "cnip" ], "outbound": "🀄️ 直连 IP" }
],
@@ -51,91 +51,104 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/private.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs",
"download_detour": "DIRECT"
},
{
"tag": "trackerslist",
"type": "remote",
"format": "binary",
"path": "./ruleset/trackerslist.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/trackerslist.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/trackerslist.srs",
"download_detour": "DIRECT"
},
{
"tag": "microsoft-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/microsoft-cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/microsoft-cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/microsoft-cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "apple-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/apple-cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/apple-cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/apple-cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "google-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/google-cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/google-cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/google-cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "games-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/games-cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games-cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games-cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "ai",
"type": "remote",
"format": "binary",
"path": "./ruleset/ai.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ai.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ai.srs",
"download_detour": "DIRECT"
},
{
"tag": "networktest",
"type": "remote",
"format": "binary",
"path": "./ruleset/networktest.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/networktest.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/networktest.srs",
"download_detour": "DIRECT"
},
{
"tag": "proxy",
"type": "remote",
"format": "binary",
"path": "./ruleset/proxy.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs",
"download_detour": "DIRECT"
},
{
"tag": "cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "privateip",
"type": "remote",
"format": "binary",
"path": "./ruleset/privateip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs",
"download_detour": "DIRECT"
},
{
"tag": "cnip",
"type": "remote",
"format": "binary",
"path": "./ruleset/cnip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs",
"download_detour": "DIRECT"
},
{
"tag": "telegramip",
"type": "remote",
"format": "binary",
"path": "./ruleset/telegramip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs",
"download_detour": "DIRECT"
}
],
"final": "🐟 漏网之鱼"

View File

@@ -0,0 +1,272 @@
//ShellCrash-ruleset 全分组规则+去广告 For Sing-box By Maozai 260111
{
"outbounds": [
{ "tag": "🚀 节点选择", "type": "selector", "outbounds": ["♻️ 自动选择", "✨ 自动选择(去高倍率)", "🛠️ 手动切换", "🎯 本地直连", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
{ "tag": "🛠️ 手动切换", "type": "selector", "use_all_providers": true, "outbounds": ["🎯 本地直连", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
{ "tag": "♻️ 自动选择", "type": "urltest", "use_all_providers": true, "exclude": "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www)" },
{ "tag": "✨ 自动选择(去高倍率)", "type": "urltest", "use_all_providers": true, "exclude": "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www|专线|专用|高级|直连|急速|高速|高倍率|游戏|铂金|钻石|企业|VIP|Ultra|Game|IEPL|IPLC|AIA|BGP|GIA|CN2|CMI|HGC|HKT|CTM|CC|AC|x([2-9]|[0-9][0-9]+))" },
{ "tag": "🤖 AI 平台", "type": "selector", "outbounds": ["🚀 节点选择", "🤖 AI节点过滤港澳", "🎯 本地直连", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
{ "tag": "🤖 AI节点过滤港澳", "type": "urltest", "use_all_providers": true, "exclude": "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www|🇭🇰|港|🇲🇴|澳门|hk|hongkong|hong kong)" },
{ "tag": "🎬 奈飞视频", "type": "selector", "outbounds": ["🚀 节点选择", "🎬 奈飞节点", "🎯 本地直连", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
{ "tag": "🎬 奈飞节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(NF|奈飞|解锁|Netflix|NETFLIX|Media)" },
{ "tag": "▶️ 油管视频", "type": "selector", "outbounds": ["🚀 节点选择", "🎯 本地直连", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
{ "tag": "📢 谷歌推送", "type": "selector", "outbounds": ["🚀 节点选择", "🎯 本地直连", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
{ "tag": "📲 电报消息", "type": "selector", "outbounds": ["🚀 节点选择", "🎯 本地直连", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
{ "tag": "🌍 国际媒体", "type": "selector", "outbounds": ["🚀 节点选择", "🎯 本地直连", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
{ "tag": "🌐 国际流量", "type": "selector", "outbounds": ["🚀 节点选择", "🎯 本地直连", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
{ "tag": "🎮 外服游戏", "type": "selector", "outbounds": ["🚀 节点选择", "🎯 本地直连", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
{ "tag": "🕹 国服游戏", "type": "selector", "outbounds": ["🎯 本地直连", "🚀 节点选择", "♻️ 自动选择", "🛠️ 手动切换", {providers_tags}] },
{ "tag": "🦾 Steam平台", "type": "selector", "outbounds": ["🎯 本地直连", "🚀 节点选择", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
{ "tag": "🪟 微软服务", "type": "selector", "outbounds": ["🎯 本地直连", "🚀 节点选择", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
{ "tag": "🍎 苹果服务", "type": "selector", "outbounds": ["🎯 本地直连", "🚀 节点选择", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
{ "tag": "🇬 谷歌服务", "type": "selector", "outbounds": ["🎯 本地直连", "🚀 节点选择", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
{ "tag": "🧲 BT下载", "type": "selector", "outbounds": ["🎯 本地直连", "🚀 节点选择", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
{ "tag": "📈 网络测速", "type": "selector", "outbounds": ["🎯 本地直连", "🚀 节点选择", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
{ "tag": "↔️ 直连软件", "type": "selector", "outbounds": ["🎯 本地直连", "🚀 节点选择", "♻️ 自动选择", "🛠️ 手动切换", {providers_tags}] },
{ "tag": "🀄️ 国内流量", "type": "selector", "outbounds": ["🎯 本地直连", "🚀 节点选择", "♻️ 自动选择", "🛠️ 手动切换", {providers_tags}] },
{ "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": ["🚀 节点选择", "🎯 本地直连", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
{ "tag": "🛑 广告拦截", "type": "selector", "outbounds": ["⛔ 禁止连接", "🔀 规则放行", "🎯 本地直连"] },
{ "tag": "⛔ 禁止连接", "type": "block" },
{ "tag": "🔀 规则放行", "type": "pass" },
{ "tag": "🎯 本地直连", "type": "direct" },
{ "tag": "GLOBAL", "type": "selector", "outbounds": ["🚀 节点选择", "🎯 本地直连"] },
{ "tag": "🇭🇰 香港节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(🇭🇰|港|hk|hongkong|hong kong)" },
{ "tag": "🇹🇼 台湾节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(🇹🇼|台|tw|taiwan|tai wan)", "exclude": "(?i)(仙台)" },
{ "tag": "🇺🇸 美国节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(🇺🇸|美|洛杉矶|圣何塞|西雅图|纽约|波特兰|旧金山|休斯|达拉斯|硅谷|堪萨斯|迈阿密|凤凰城|芝加哥|奥勒姆|us|unitedstates|united states)", "exclude": "(?i)(南美|中美|拉美|亚美尼亚|美属)" },
{ "tag": "🇯🇵 日本节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(🇯🇵|日|东京|大阪|埼玉|九州|jp|japan)", "exclude": "(?i)(尼日利亚|尼日尔|日内瓦)" },
{ "tag": "🇪🇺 欧洲节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(🇪🇺|欧|德|英|法|荷|俄罗斯|西班牙|意大利|瑞士|瑞典|土耳其|挪威|芬兰|丹麦|比利时|爱尔兰|奥地利|波兰|葡萄牙|乌克兰|希腊|捷克|匈牙利|罗马尼亚|保加利亚|冰岛|克罗地亚|阿姆斯特丹)" },
{ "tag": "🇰🇷 韩国节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(🇰🇷|韩|韓|首尔|kr|kor)" },
{ "tag": "🇸🇬 狮城节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(🇸🇬|新加坡|狮城|sg|singapore)" },
{ "tag": "👑 高级节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(专线|专用|高级|直连|急速|高速|高倍率|游戏|铂金|钻石|企业|VIP|Ultra|Game|IEPL|IPLC|AIA|BGP|GIA|CN2|CMI|HGC|HKT|CTM|CC|AC|x([2-9]|[0-9][0-9]+))" },
{ "tag": "📉 省流节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(0[.][1-5]|低倍率|省流|大流量|公益|免费|闲时|Low)" }
],
"route": {
"rules": [
{ "domain_suffix": ["captive.apple.com"], "outbound": "🍎 苹果服务" },
{ "domain_suffix": ["kamo.teracloud.jp"], "outbound": "🀄️ 国内流量" },
{ "rule_set": ["private"], "outbound": "🎯 本地直连" },
{ "rule_set": ["ads"], "outbound": "🛑 广告拦截" },
{ "rule_set": ["networktest"], "outbound": "📈 网络测速" },
{ "rule_set": ["applications"], "outbound": "↔️ 直连软件" },
{ "rule_set": ["trackerslist"], "outbound": "🧲 BT下载" },
{ "rule_set": ["apple-cn"], "outbound": "🍎 苹果服务" },
{ "rule_set": ["microsoft-cn"], "outbound": "🪟 微软服务" },
{ "rule_set": ["google-cn"], "outbound": "🇬 谷歌服务" },
{ "rule_set": ["steamcn"], "outbound": "🦾 Steam平台" },
{ "rule_set": ["games-cn"], "outbound": "🕹 国服游戏" },
{ "rule_set": ["googlefcm"], "outbound": "📢 谷歌推送" },
{ "rule_set": ["netflix"], "outbound": "🎬 奈飞视频" },
{ "rule_set": ["youtube"], "outbound": "▶️ 油管视频" },
{ "rule_set": ["ai"], "outbound": "🤖 AI 平台" },
{ "rule_set": ["media"], "outbound": "🌍 国际媒体" },
{ "rule_set": ["games"], "outbound": "🎮 外服游戏" },
{ "rule_set": ["proxy"], "outbound": "🌐 国际流量" },
{ "rule_set": ["cn"], "outbound": "🀄️ 国内流量" },
{ "rule_set": ["privateip"], "outbound": "🎯 本地直连" },
{ "rule_set": ["telegramip"], "outbound": "📲 电报消息" },
{ "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4" },
{ "rule_set": ["gamesip"], "outbound": "🎮 外服游戏" },
{ "rule_set": ["mediaip"], "outbound": "🌍 国际媒体" },
{ "rule_set": ["cnip"], "outbound": "🀄️ 国内流量" }
],
"rule_set": [
{
"tag": "private",
"type": "remote",
"format": "binary",
"path": "./ruleset/private.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/private.srs",
"download_detour": "DIRECT"
},
{
"tag": "ads",
"type": "remote",
"format": "binary",
"path": "./ruleset/ads.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/ads.srs",
"download_detour": "DIRECT"
},
{
"tag": "networktest",
"type": "remote",
"format": "binary",
"path": "./ruleset/networktest.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/networktest.srs",
"download_detour": "DIRECT"
},
{
"tag": "applications",
"type": "remote",
"format": "binary",
"path": "./ruleset/applications.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/applications.srs",
"download_detour": "DIRECT"
},
{
"tag": "trackerslist",
"type": "remote",
"format": "binary",
"path": "./ruleset/trackerslist.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/trackerslist.srs",
"download_detour": "DIRECT"
},
{
"tag": "apple-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/apple-cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/apple-cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "microsoft-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/microsoft-cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/microsoft-cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "google-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/google-cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/google-cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "steamcn",
"type": "remote",
"format": "binary",
"path": "./ruleset/steamcn.srs",
"url": "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@refs/heads/sing/geo/geosite/steam%40cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "games-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/games-cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/games-cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "googlefcm",
"type": "remote",
"format": "binary",
"path": "./ruleset/googlefcm.srs",
"url": "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@refs/heads/sing/geo/geosite/googlefcm.srs",
"download_detour": "DIRECT"
},
{
"tag": "netflix",
"type": "remote",
"format": "binary",
"path": "./ruleset/netflix.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/netflix.srs",
"download_detour": "DIRECT"
},
{
"tag": "youtube",
"type": "remote",
"format": "binary",
"path": "./ruleset/youtube.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/youtube.srs",
"download_detour": "DIRECT"
},
{
"tag": "ai",
"type": "remote",
"format": "binary",
"path": "./ruleset/ai.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/ai.srs",
"download_detour": "DIRECT"
},
{
"tag": "media",
"type": "remote",
"format": "binary",
"path": "./ruleset/media.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/media.srs",
"download_detour": "DIRECT"
},
{
"tag": "games",
"type": "remote",
"format": "binary",
"path": "./ruleset/games.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/games.srs",
"download_detour": "DIRECT"
},
{
"tag": "proxy",
"type": "remote",
"format": "binary",
"path": "./ruleset/proxy.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/proxy.srs",
"download_detour": "DIRECT"
},
{
"tag": "cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "privateip",
"type": "remote",
"format": "binary",
"path": "./ruleset/privateip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/privateip.srs",
"download_detour": "DIRECT"
},
{
"tag": "telegramip",
"type": "remote",
"format": "binary",
"path": "./ruleset/telegramip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/telegramip.srs",
"download_detour": "DIRECT"
},
{
"tag": "gamesip",
"type": "remote",
"format": "binary",
"path": "./ruleset/gamesip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/gamesip.srs",
"download_detour": "DIRECT"
},
{
"tag": "mediaip",
"type": "remote",
"format": "binary",
"path": "./ruleset/mediaip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/mediaip.srs",
"download_detour": "DIRECT"
},
{
"tag": "cnip",
"type": "remote",
"format": "binary",
"path": "./ruleset/cnip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/cnip.srs",
"download_detour": "DIRECT"
}
],
"final": "🐟 漏网之鱼"
}
}

View File

@@ -1,16 +1,16 @@
//ShellCrash-ruleset极简规则
{
"outbounds": [
{ "tag": "🚀 节点选择", "type": "selector", "outbounds": [ {providers_tags}, "DIRECT" ], "use_all_providers": true },
{ "tag": "🎯 全球直连", "type": "selector", "outbounds": [ "DIRECT", "🚀 节点选择" ] }
{ "tag": "🚀 节点选择", "type": "selector", "outbounds": [ {providers_tags}, "🎯 本地直连" ], "use_all_providers": true },
{ "tag": "🎯 本地直连", "type": "direct" }
],
"route": {
"rules": [
{ "rule_set": [ "privateip" ], "outbound": "🎯 全球直连" },
{ "rule_set": [ "cn" ], "outbound": "🎯 全球直连" },
{ "rule_set": [ "privateip" ], "outbound": "🎯 本地直连" },
{ "rule_set": [ "cn" ], "outbound": "🎯 本地直连" },
{ "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4"},
{ "rule_set": [ "cnip" ], "outbound": "🎯 全球直连" }
{ "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4", "match_only": true},
{ "rule_set": [ "cnip" ], "outbound": "🎯 本地直连" }
],
"rule_set": [
{
@@ -18,21 +18,24 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/cn.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs",
"download_detour": "DIRECT"
},
{
"tag": "privateip",
"type": "remote",
"format": "binary",
"path": "./ruleset/privateip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs",
"download_detour": "DIRECT"
},
{
"tag": "cnip",
"type": "remote",
"format": "binary",
"path": "./ruleset/cnip.srs",
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs"
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs",
"download_detour": "DIRECT"
}
],
"final": "🚀 节点选择"

View File

@@ -1,4 +1,5 @@
ShellCrash-ruleset极简规则 ShellCrash_RS_Nano.json
ShellCrash-ruleset全分组规则+去广告 ShellCrash_RS_Full_BanAds.json
DustinWin-ruleset轻量规则 DustinWin_RS_Light.json
DustinWin-ruleset标准规则 DustinWin_RS_Lite_NoAds.json
DustinWin-ruleset标准规则+去广告 DustinWin_RS_Lite.json

View File

@@ -1,161 +1,6 @@
#!/bin/sh
# Copyright (C) Juewuy
setdir() {
dir_avail() {
df $2 $1 | awk '{ for(i=1;i<=NF;i++){ if(NR==1){ arr[i]=$i; }else{ arr[i]=arr[i]" "$i; } } } END{ for(i=1;i<=NF;i++){ print arr[i]; } }' | grep -E 'Ava|可用' | awk '{print $2}'
}
set_usb_dir() {
echo -e "请选择安装目录"
du -hL /mnt | awk '{print " "NR" "$2" "$1}'
read -p "请输入相应数字 > " num
dir=$(du -hL /mnt | awk '{print $2}' | sed -n "$num"p)
if [ -z "$dir" ]; then
echo -e "\033[31m输入错误请重新设置\033[0m"
set_usb_dir
fi
}
set_asus_dir() {
echo -e "请选择U盘目录"
du -hL /tmp/mnt | awk -F/ 'NF<=4' | awk '{print " "NR" "$2" "$1}'
read -p "请输入相应数字 > " num
dir=$(du -hL /tmp/mnt | awk -F/ 'NF<=4' | awk '{print $2}' | sed -n "$num"p)
if [ ! -f "$dir/asusware.arm/etc/init.d/S50downloadmaster" ]; then
echo -e "\033[31m未找到下载大师自启文件$dir/asusware.arm/etc/init.d/S50downloadmaster请检查设置\033[0m"
set_asus_dir
fi
}
set_cust_dir() {
echo "-----------------------------------------------"
echo "可用路径 剩余空间:"
df -h | awk '{print $6,$4}' | sed 1d
echo "路径是必须带 / 的格式,注意写入虚拟内存(/tmp,/opt,/sys...)的文件会在重启后消失!!!"
read -p "请输入自定义路径 > " dir
if [ "$(dir_avail $dir)" = 0 ] || [ -n "$(echo $dir | grep -E 'tmp|opt|sys')" ]; then
echo "\033[31m路径错误请重新设置\033[0m"
set_cust_dir
fi
}
echo "-----------------------------------------------"
if [ -n "$systype" ]; then
[ "$systype" = "Padavan" ] && dir=/etc/storage
[ "$systype" = "mi_snapshot" ] && {
echo -e "\033[33m检测到当前设备为小米官方系统请选择安装位置\033[0m"
[ -d /data ] && $echo " 1 安装到 /data 目录,剩余空间:$(dir_avail /data -h)(支持软固化功能)"
[ -d /userdisk ] && $echo " 2 安装到 /userdisk 目录,剩余空间:$(dir_avail /userdisk -h)(支持软固化功能)"
[ -d /data/other_vol ] && $echo " 3 安装到 /data/other_vol 目录,剩余空间:$(dir_avail /data/other_vol -h)(支持软固化功能)"
$echo " 4 安装到自定义目录(不推荐,不明勿用!)"
echo " 0 退出安装"
echo "-----------------------------------------------"
read -p "请输入相应数字 > " num
case "$num" in
1)
dir=/data
;;
2)
dir=/userdisk
;;
3)
dir=/data/other_vol
;;
4)
set_cust_dir
;;
*)
exit 1
;;
esac
}
[ "$systype" = "asusrouter" ] && {
echo -e "\033[33m检测到当前设备为华硕固件请选择安装方式\033[0m"
echo -e " 1 基于USB设备安装(限23年9月之前固件须插入\033[31m任意\033[0mUSB设备)"
echo -e " 2 基于自启脚本安装(仅支持梅林及部分非koolshare官改固件)"
echo -e " 3 基于U盘+下载大师安装(支持所有固件限ARM设备须插入U盘或移动硬盘)"
echo -e " 0 退出安装"
echo "-----------------------------------------------"
read -p "请输入相应数字 > " num
case "$num" in
1)
read -p "将脚本安装到USB存储/系统闪存?(1/0) > " res
[ "$res" = "1" ] && set_usb_dir || dir=/jffs
usb_status=1
;;
2)
echo -e "如无法正常开机启动请重新使用USB方式安装"
sleep 2
dir=/jffs
;;
3)
echo -e "请先在路由器网页后台安装下载大师并启用,之后选择外置存储所在目录!"
sleep 2
set_asus_dir
;;
*)
exit 1
;;
esac
}
[ "$systype" = "ng_snapshot" ] && dir=/tmp/mnt
else
echo -e "\033[33m安装ShellCrash至少需要预留约1MB的磁盘空间\033[0m"
echo -e " 1 在\033[32m/etc目录\033[0m下安装(适合root用户)"
echo -e " 2 在\033[32m/usr/share目录\033[0m下安装(适合Linux系统)"
echo -e " 3 在\033[32m当前用户目录\033[0m下安装(适合非root用户)"
echo -e " 4 在\033[32m外置存储\033[0m中安装"
echo -e " 5 手动设置安装目录"
echo -e " 0 退出安装"
echo "-----------------------------------------------"
read -p "请输入相应数字 > " num
#设置目录
case "$num" in
1)
dir=/etc
;;
2)
dir=/usr/share
;;
3)
dir=~/.local/share
mkdir -p ~/.config/systemd/user
;;
4)
set_usb_dir
;;
5)
echo "-----------------------------------------------"
echo "可用路径 剩余空间:"
df -h | awk '{print $6,$4}' | sed 1d
echo "路径是必须带 / 的格式,注意写入虚拟内存(/tmp,/opt,/sys...)的文件会在重启后消失!!!"
read -p "请输入自定义路径 > " dir
if [ -z "$dir" ]; then
echo -e "\033[31m路径错误请重新设置\033[0m"
setdir
fi
;;
*)
echo "安装已取消"
exit 1
;;
esac
fi
if [ ! -w $dir ]; then
echo -e "\033[31m没有$dir目录写入权限!请重新设置!\033[0m" && sleep 1 && setdir
else
echo -e "目标目录\033[32m$dir\033[0m空间剩余$(dir_avail $dir -h)"
read -p "确认安装?(1/0) > " res
[ "$res" = "1" ] && CRASHDIR=$dir/ShellCrash || setdir
fi
}
setconfig() { #脚本配置工具
#参数1代表变量名参数2代表变量值,参数3即文件路径
[ -z "$3" ] && configpath="$CRASHDIR"/configs/ShellCrash.cfg || configpath="${3}"
if grep -q "^${1}=" "$configpath"; then
sed -i "s#^${1}=.*#${1}=${2}#g" "$configpath"
else
printf '%s=%s\n' "$1" "$2" >>"$configpath"
fi
}
#特殊固件识别及标记
[ -f "/etc/storage/started_script.sh" ] && { #老毛子固件
systype=Padavan
@@ -176,22 +21,26 @@ grep -qE '/(docker|lxc|kubepods|crio|containerd)/' /proc/1/cgroup || [ -f /run/.
#检查环境变量
[ "$systype" = 'container' ] && CRASHDIR='/etc/ShellCrash'
[ -z "$CRASHDIR" ] && [ -n "$clashdir" ] && CRASHDIR="$clashdir"
[ -z "$CRASHDIR" ] && [ -d /tmp/SC_tmp ] && setdir
[ -z "$CRASHDIR" ] && [ -d /tmp/SC_tmp ] && . /tmp/SC_tmp/menus/set_crashdir.sh && set_crashdir
#移动文件
mkdir -p ${CRASHDIR}
mv -f /tmp/SC_tmp/* ${CRASHDIR} 2>/dev/null
mkdir -p "$CRASHDIR"
rm -rf /tmp/SC_tmp/menus/set_crashdir.sh
mv -f /tmp/SC_tmp/* "$CRASHDIR" 2>/dev/null
##############################
#注意目录变更
CFG_PATH="$CRASHDIR"/configs/ShellCrash.cfg
. "$CRASHDIR"/libs/set_config.sh
. "$CRASHDIR"/libs/set_profile.sh
#初始化
mkdir -p ${CRASHDIR}/configs
[ -f "${CRASHDIR}/configs/ShellCrash.cfg" ] || echo '#ShellCrash配置文件不明勿动' >${CRASHDIR}/configs/ShellCrash.cfg
mkdir -p "$CRASHDIR"/configs
[ -f "$CFG_PATH" ] || echo '#ShellCrash配置文件不明勿动' >"$CFG_PATH"
#判断系统类型写入不同的启动文件
[ -w /usr/lib/systemd/system ] && sysdir=/usr/lib/systemd/system
[ -w /etc/systemd/system ] && sysdir=/etc/systemd/system
if [ -f /etc/rc.common -a "$(cat /proc/1/comm)" = "procd" ]; then
#设为init.d方式启动
cp -f ${CRASHDIR}/shellcrash.procd /etc/init.d/shellcrash
cp -f "$CRASHDIR"/starts/shellcrash.procd /etc/init.d/shellcrash
chmod 755 /etc/init.d/shellcrash
rm -rf ${CRASHDIR}/shellcrash.openrc
elif [ -n "$sysdir" -a "$USER" = "root" -a "$(cat /proc/1/comm)" = "systemd" ]; then
#创建shellcrash用户
userdel shellcrash 2>/dev/null
@@ -204,41 +53,46 @@ elif [ -n "$sysdir" -a "$USER" = "root" -a "$(cat /proc/1/comm)" = "systemd" ];
echo "shellcrash:x:0:7890::/home/shellcrash:/bin/sh" >>/etc/passwd
fi
#配置systemd
mv -f ${CRASHDIR}/shellcrash.service $sysdir/shellcrash.service 2>/dev/null
sed -i "s%/etc/ShellCrash%$CRASHDIR%g" $sysdir/shellcrash.service
mv -f "$CRASHDIR"/starts/shellcrash.service "$sysdir"/shellcrash.service 2>/dev/null
sed -i "s%/etc/ShellCrash%$CRASHDIR%g" "$sysdir"/shellcrash.service
systemctl daemon-reload
rm -rf "$CRASHDIR"/starts/shellcrash.procd
elif rc-status -r >/dev/null 2>&1; then
#设为openrc方式启动
cp -f ${CRASHDIR}/shellcrash.openrc /etc/init.d/shellcrash
mv -f "$CRASHDIR"/starts/shellcrash.openrc /etc/init.d/shellcrash
chmod 755 /etc/init.d/shellcrash
rm -rf ${CRASHDIR}/shellcrash.procd
rm -rf "$CRASHDIR"/starts/shellcrash.procd
else
#设为保守模式启动
setconfig start_old 已开启
rm -rf "$CRASHDIR"/starts/shellcrash.procd
fi
rm -rf "$CRASHDIR"/starts/shellcrash.service
rm -rf "$CRASHDIR"/starts/shellcrash.openrc
#修饰文件及版本号
command -v bash >/dev/null 2>&1 && shtype=bash
[ -x /bin/ash ] && shtype=ash
for file in start.sh task.sh menu.sh; do
sed -i "s|/bin/sh|/bin/$shtype|" ${CRASHDIR}/${file} 2>/dev/null
chmod 755 ${CRASHDIR}/${file} 2>/dev/null
#批量授权
for file in start.sh starts/bfstart.sh starts/afstart.sh starts/fw_stop.sh menu.sh menus/task_cmd.sh menus/bot_tg.sh; do
sed -i "s|/bin/sh|/bin/$shtype|" "$CRASHDIR/$file" 2>/dev/null
chmod +x "$CRASHDIR/$file" 2>/dev/null
done
setconfig versionsh_l $version
#生成用于执行启动服务的变量文件
[ ! -f ${CRASHDIR}/configs/command.env ] && {
[ ! -f "$CRASHDIR"/configs/command.env ] && {
TMPDIR='/tmp/ShellCrash'
BINDIR=${CRASHDIR}
touch ${CRASHDIR}/configs/command.env
setconfig TMPDIR ${TMPDIR} ${CRASHDIR}/configs/command.env
setconfig BINDIR ${BINDIR} ${CRASHDIR}/configs/command.env
BINDIR="$CRASHDIR"
touch "$CRASHDIR"/configs/command.env
setconfig TMPDIR "$TMPDIR" "$CRASHDIR"/configs/command.env
setconfig BINDIR "$BINDIR" "$CRASHDIR"/configs/command.env
}
if [ -n "$(grep 'crashcore=singbox' ${CRASHDIR}/configs/ShellCrash.cfg)" ]; then
if [ -n "$(grep 'crashcore=singbox' "$CFG_PATH")" ]; then
COMMAND='"$TMPDIR/CrashCore run -D $BINDIR -C $TMPDIR/jsons"'
else
COMMAND='"$TMPDIR/CrashCore -d $BINDIR -f $TMPDIR/config.yaml"'
fi
setconfig COMMAND "$COMMAND" ${CRASHDIR}/configs/command.env
setconfig COMMAND "$COMMAND" "$CRASHDIR"/configs/command.env
#设置防火墙执行模式
grep -q 'firewall_mod' "$CRASHDIR/configs/ShellClash.cfg" 2>/dev/null || {
firewall_mod=iptables
@@ -246,22 +100,18 @@ grep -q 'firewall_mod' "$CRASHDIR/configs/ShellClash.cfg" 2>/dev/null || {
setconfig firewall_mod $firewall_mod
}
#设置更新地址
[ -n "$url" ] && setconfig update_url $url
[ -n "$url" ] && setconfig update_url "$url"
[ -n "$release_type" ] && setconfig release_type "$release_type"
#设置语言
[ -n "$language" ] && echo "$language" > "$CRASHDIR/configs/i18n.cfg"
#设置环境变量
[ -w /opt/etc/profile ] && profile=/opt/etc/profile
[ -w /opt/etc/profile ] && [ "$systype" = "Padavan" ] && profile=/opt/etc/profile
[ -w /jffs/configs/profile.add ] && profile=/jffs/configs/profile.add
[ -z "$profile" ] && profile=/etc/profile
set_profile() {
[ -z "$my_alias" ] && my_alias=crash
sed -i "/ShellCrash\/menu.sh/"d "$1"
echo "alias ${my_alias}=\"$shtype $CRASHDIR/menu.sh\"" >>"$1" #设置快捷命令环境变量
sed -i '/export CRASHDIR=*/'d "$1"
echo "export CRASHDIR=\"$CRASHDIR\"" >>"$1" #设置路径环境变量
}
if [ -n "$profile" ]; then
set_profile "$profile"
#适配zsh环境变量
zsh --version >/dev/null 2>&1 && [ -z "$(cat $HOME/.zshrc 2>/dev/null | grep CRASHDIR)" ] && set_profile '$HOME/.zshrc'
zsh --version >/dev/null 2>&1 && [ -z "$(cat $HOME/.zshrc 2>/dev/null | grep CRASHDIR)" ] && set_profile "$HOME/.zshrc"
setconfig my_alias "$my_alias"
else
echo -e "\033[33m无法写入环境变量请检查安装权限\033[0m"
@@ -269,30 +119,39 @@ else
fi
#梅林/Padavan额外设置
[ -n "$initdir" ] && {
sed -i '/ShellCrash初始化/'d $initdir
touch $initdir
echo "$CRASHDIR/start.sh init & #ShellCrash初始化脚本" >>$initdir
chmod a+rx $initdir 2>/dev/null
setconfig initdir $initdir
touch "$initdir"
sed -i '/ShellCrash初始化/'d "$initdir"
echo "$CRASHDIR/starts/general_init.sh & #ShellCrash初始化脚本" >>"$initdir"
chmod 755 "$CRASHDIR"/starts/general_init.sh
chmod a+rx "$initdir" 2>/dev/null
setconfig initdir "$initdir"
}
#Padavan额外设置
[ -f "/etc/storage/started_script.sh" ] && mount -t tmpfs -o remount,rw,size=45M tmpfs /tmp #增加/tmp空间以适配新的内核压缩方式
#镜像化OpenWrt(snapshot)额外设置
if [ "$systype" = "mi_snapshot" -o "$systype" = "ng_snapshot" ]; then
chmod 755 ${CRASHDIR}/misnap_init.sh
uci delete firewall.ShellClash 2>/dev/null
chmod 755 "$CRASHDIR"/starts/snapshot_init.sh
if [ "$systype" = "mi_snapshot" ];then
path="/data/shellcrash_init.sh"
sed -i "s#^CRASHDIR=.*#CRASHDIR=$CRASHDIR#" "$CRASHDIR"/starts/snapshot_init.sh
mv -f "$CRASHDIR"/starts/snapshot_init.sh "$path"
[ ! -f /data/auto_start.sh ] && echo '#用于自定义需要开机启动的功能或者命令,会在开机后自动运行' > /data/auto_start.sh
else
path="$CRASHDIR"/starts/snapshot_init.sh
fi
uci delete firewall.auto_ssh 2>/dev/null
uci delete firewall.ShellCrash 2>/dev/null
uci set firewall.ShellCrash=include
uci set firewall.ShellCrash.type='script'
uci set firewall.ShellCrash.path="$CRASHDIR/misnap_init.sh"
uci set firewall.ShellCrash.path="$path"
uci set firewall.ShellCrash.enabled='1'
uci commit firewall
else
rm -rf ${CRASHDIR}/misnap_init.sh
rm -rf "$CRASHDIR"/starts/snapshot_init.sh
fi
#华硕USB启动额外设置
[ "$usb_status" = "1" ] && {
echo "$CRASHDIR/start.sh init & #ShellCrash初始化脚本" >${CRASHDIR}/asus_usb_mount.sh
echo "$CRASHDIR/start.sh init & #ShellCrash初始化脚本" >"$CRASHDIR"/asus_usb_mount.sh
nvram set script_usbmount="$CRASHDIR/asus_usb_mount.sh"
nvram commit
}
@@ -307,7 +166,7 @@ fi
setconfig firewall_area '1'
setconfig firewall_mod 'nftables'
setconfig release_type 'master'
setconfig start_old '未开启'
setconfig start_old 'OFF'
echo "$CRASHDIR/menu.sh" >> /etc/profile
cat > /usr/bin/crash <<'EOF'
#!/bin/sh
@@ -322,57 +181,57 @@ setconfig systype $systype
rm -rf /tmp/*rash*gz
rm -rf /tmp/SC_tmp
#转换&清理旧版本文件
mkdir -p ${CRASHDIR}/yamls
mkdir -p ${CRASHDIR}/jsons
mkdir -p ${CRASHDIR}/tools
mkdir -p ${CRASHDIR}/task
mkdir -p ${CRASHDIR}/ruleset
mkdir -p "$CRASHDIR"/yamls
mkdir -p "$CRASHDIR"/jsons
mkdir -p "$CRASHDIR"/tools
mkdir -p "$CRASHDIR"/task
mkdir -p "$CRASHDIR"/ruleset
for file in config.yaml.bak user.yaml proxies.yaml proxy-groups.yaml rules.yaml others.yaml; do
mv -f ${CRASHDIR}/$file ${CRASHDIR}/yamls/$file 2>/dev/null
mv -f "$CRASHDIR"/"$file" "$CRASHDIR"/yamls/"$file" 2>/dev/null
done
[ ! -L ${CRASHDIR}/config.yaml ] && mv -f ${CRASHDIR}/config.yaml ${CRASHDIR}/yamls/config.yaml 2>/dev/null
[ ! -L "$CRASHDIR"/config.yaml ] && mv -f "$CRASHDIR"/config.yaml "$CRASHDIR"/yamls/config.yaml 2>/dev/null
for file in fake_ip_filter mac web_save servers.list fake_ip_filter.list fallback_filter.list singbox_providers.list clash_providers.list; do
mv -f ${CRASHDIR}/$file ${CRASHDIR}/configs/$file 2>/dev/null
mv -f "$CRASHDIR"/"$file" "$CRASHDIR"/configs/"$file" 2>/dev/null
done
#配置文件改名
mv -f ${CRASHDIR}/mark ${CRASHDIR}/configs/ShellCrash.cfg 2>/dev/null
mv -f ${CRASHDIR}/configs/ShellClash.cfg ${CRASHDIR}/configs/ShellCrash.cfg 2>/dev/null
mv -f "$CRASHDIR"/configs/ShellClash.cfg "$CFG_PATH" 2>/dev/null
#数据库改名
mv -f ${CRASHDIR}/geosite.dat ${CRASHDIR}/GeoSite.dat 2>/dev/null
mv -f ${CRASHDIR}/ruleset/geosite-cn.srs ${CRASHDIR}/ruleset/cn.srs 2>/dev/null
mv -f ${CRASHDIR}/ruleset/geosite-cn.mrs ${CRASHDIR}/ruleset/cn.mrs 2>/dev/null
mv -f "$CRASHDIR"/geosite.dat "$CRASHDIR"/GeoSite.dat 2>/dev/null
mv -f "$CRASHDIR"/ruleset/geosite-cn.srs "$CRASHDIR"/ruleset/cn.srs 2>/dev/null
mv -f "$CRASHDIR"/ruleset/geosite-cn.mrs "$CRASHDIR"/ruleset/cn.mrs 2>/dev/null
#数据库移动
mv -f ${CRASHDIR}/*.srs ${CRASHDIR}/ruleset/ 2>/dev/null
mv -f ${CRASHDIR}/*.mrs ${CRASHDIR}/ruleset/ 2>/dev/null
#内核改名
mv -f ${CRASHDIR}/clash ${CRASHDIR}/CrashCore 2>/dev/null
#内核压缩
[ -f ${CRASHDIR}/CrashCore ] && tar -zcf ${CRASHDIR}/CrashCore.tar.gz -C ${CRASHDIR} CrashCore
mv -f "$CRASHDIR"/*.srs "$CRASHDIR"/ruleset/ 2>/dev/null
mv -f "$CRASHDIR"/*.mrs "$CRASHDIR"/ruleset/ 2>/dev/null
for file in dropbear_rsa_host_key authorized_keys tun.ko ShellDDNS.sh; do
mv -f ${CRASHDIR}/$file ${CRASHDIR}/tools/$file 2>/dev/null
mv -f "$CRASHDIR"/"$file" "$CRASHDIR"/tools/"$file" 2>/dev/null
done
for file in cron task.sh task.list; do
mv -f ${CRASHDIR}/$file ${CRASHDIR}/task/$file 2>/dev/null
for file in cron task.list; do
mv -f "$CRASHDIR"/"$file" "$CRASHDIR"/task/"$file" 2>/dev/null
done
mv -f "$CRASHDIR"/menus/task_cmd.sh "$CRASHDIR"/task/task.sh 2>/dev/null
#旧版文件清理
userdel shellclash >/dev/null 2>&1
sed -i '/shellclash/d' /etc/passwd
sed -i '/shellclash/d' /etc/group
rm -rf /etc/init.d/clash
rm -rf ${CRASHDIR}/rules
rm -rf "$CRASHDIR"/rules
[ "$systype" = "mi_snapshot" -a "$CRASHDIR" != '/data/clash' ] && rm -rf /data/clash
for file in CrashCore clash.sh getdate.sh core.new clashservice log shellcrash.service mark? mark.bak; do
rm -rf ${CRASHDIR}/$file
for file in webget.sh misnap_init.sh core.new configs/ShellCrash.cfg.bak; do
rm -f "$CRASHDIR/$file"
done
#旧版变量改名
sed -i "s/clashcore/crashcore/g" $configpath
sed -i "s/clash_v/core_v/g" $configpath
sed -i "s/clash.meta/meta/g" $configpath
sed -i "s/ShellClash/ShellCrash/g" $configpath
sed -i "s/cpucore=armv8/cpucore=arm64/g" $configpath
sed -i "s/redir_mod=Nft基础/redir_mod=Redir模式/g" $configpath
sed -i "s/redir_mod=Nft混合/redir_mod=Tproxy模式/g" $configpath
sed -i "s/redir_mod=Tproxy混合/redir_mod=Tproxy模式/g" $configpath
sed -i "s/redir_mod=纯净模式/firewall_area=4/g" $configpath
sed -i "s/clashcore/crashcore/g" "$CFG_PATH"
sed -i "s/clash_v/core_v/g" "$CFG_PATH"
sed -i "s/clash.meta/meta/g" "$CFG_PATH"
sed -i "s/ShellClash/ShellCrash/g" "$CFG_PATH"
sed -i "s/cpucore=armv8/cpucore=arm64/g" "$CFG_PATH"
sed -i "s/redir_mod=Redir模式/redir_mod=Redir/g" "$CFG_PATH"
sed -i "s/redir_mod=Tproxy模式/redir_mod=Tproxy/g" "$CFG_PATH"
sed -i "s/redir_mod=Tun模式/redir_mod=Tun/g" "$CFG_PATH"
sed -i "s/redir_mod=混合模式/redir_mod=Mix/g" "$CFG_PATH"
sed -i "s/redir_mod=纯净模式/firewall_area=4/g" "$CFG_PATH"
#变量统一使用ON/OFF
sed -i 's/=\(已启用\|已开启\)$/=ON/' "$CFG_PATH"
sed -i 's/=\(未启用\|未开启\)$/=OFF/' "$CFG_PATH"
echo -e "\033[32m脚本初始化完成,请输入\033[30;47m $my_alias \033[0;33m命令开始使用\033[0m"
printf '\033[32m脚本初始化完成,请输入\033[30;47m %s \033[0;33m命令开始使用\033[0m\n' "$my_alias"

View File

@@ -0,0 +1,11 @@
# ===== 启动完成 =====
START_SERVICE_OK="服务已启动!"
START_WEB_HINT="请前往"
START_WEB_HINT2="管理内置规则"
START_PAC_HINT="其他设备可使用 PAC 配置:"
START_PROXY_HINT="或使用 HTTP / SOCKS5 方式连接:"
# ===== 启动流程 =====
START_NO_CORE_CFG_TRY_GEN="没有找到核心配置文件,尝试生成 providers 配置文件!"
START_NO_CORE_CFG_IMPORT_FIRST="没有找到核心配置文件,请先导入配置文件!"
START_FIREWALL_DONE="已完成防火墙设置!"

View File

@@ -0,0 +1,133 @@
# =================================================
# Settings main menu
# =================================================
SET_MENU_TITLE="功能设置菜单"
SET_MENU_REDIR="路由模式设置:"
SET_MENU_DNS="DNS设置 "
SET_MENU_FW_FILTER="透明路由流量过滤"
SET_MENU_SKIP_CERT="跳过证书验证:"
SET_MENU_SNIFFER="启用域名嗅探:"
SET_MENU_ADV_PORT="自定义端口及密钥"
SET_MENU_IPV6="IPv6设置 "
SET_MENU_RESET="重置/备份/还原脚本设置"
SET_MENU_LANG="多语言切换"
SET_MENU_UI="UI切换"
# =================================================
# Main menu messages
# =================================================
SET_WARN_NONROOT="非root用户可能无法正确配置其他模式是否继续"
SET_SKIP_CERT_ON="已启用跳过本地证书验证!"
SET_SKIP_CERT_OFF="已禁用跳过本地证书验证!"
SET_SNIFFER_CORE_SWITCH="已自动切换至Meta内核域名嗅探需要"
SET_SNIFFER_LOCKED="当前内核与DNS模式组合下域名嗅探无法关闭"
SET_CORE_RUNNING="检测到服务正在运行,需要先停止服务!"
SET_CORE_STOP_CONFIRM="是否确认停止服务:"
# =================================================
# Backup / Restore / Reset
# =================================================
SET_BACKUP="备份脚本设置"
SET_RESTORE="还原脚本设置"
SET_RESET="重置脚本设置"
SET_BACKUP_OK="备份脚本设置成功!"
SET_BACKUP_FAIL="备份脚本设置失败!"
SET_RESTORE_OK="脚本设置已还原!(被覆盖配置已备份)"
SET_RESET_OK="重置脚本设置成功!(旧配置已备份)"
SET_RESET_FAIL="重置脚本设置失败!"
SET_BACKUP_MISS="未找到备份文件,请先备份!"
SET_NEED_RESTART="请重新启动脚本以生效!"
# =================================================
# Redir mode
# =================================================
SET_REDIR_DEFAULT="Redir模式"
SET_REDIR_CURRENT="当前路由模式为:"
SET_CORE_CURRENT="ShellCrash 核心为:"
SET_REDIR_RESTART_HINT="注意:切换模式后需要手动重启服务以生效!"
SET_REDIR_APPLIED="已设为"
SET_REDIR_REDIR="Redir模式"
SET_REDIR_MIX="Mix模式"
SET_REDIR_TPROXY="Tproxy模式"
SET_REDIR_TUN="Tun模式"
SET_REDIR_REDIRDES="Redir转发TCP不转发UDP"
SET_REDIR_MIXDES="Redir转发TCPTun转发UDP"
SET_REDIR_TPROXYDES="Tproxy转发TCP&UDP"
SET_REDIR_TUNDES="Tun转发TCP&UDP占用高不推荐"
SET_NO_MOD="设备未检测到内核模块:"
SET_NO_MOD2="请尝试其他模式或者安装相关依赖!"
XIAOMI_QOS="小米设备的 QoS 服务与当前模式冲突,是否禁用相关功能?"
# =================================================
# Firewall / VM
# =================================================
SET_FW_AREA="设置路由劫持范围"
SET_VM_REDIR="容器/虚拟机劫持"
SET_FW_SWITCH="切换防火墙应用"
SET_FW_AREA_DESC="仅局域网|仅本机|局域网+本机|纯净模式|旁路转发"
FW_AREA_NOTE_1="如你使用了第三方DNS如smartdns等"
FW_AREA_NOTE_2="请勿启用本机劫持或使用shellcrash用户执行"
FW_AREA_LAN="仅劫持局域网流量"
FW_AREA_LOCAL="仅劫持本机流量"
FW_AREA_BOTH="劫持局域网 + 本机流量"
FW_AREA_NONE="不配置流量劫持(纯净模式)"
FW_NO_NFTABLES="当前设备未安装 nftables或 nftables 版本过低(< 1.0.2),无法切换!"
FW_NO_IPTABLES="当前设备未安装 iptables无法切换"
FW_NO_FIREWALL_BACKEND="检测不到可用的防火墙应用iptables / nftables无法切换"
VM_DETECT_DESC="默认的容器/虚拟机网段为:"
VM_ENABLE_AUTO="启用劫持并使用自动检测的网段"
VM_ENABLE_MANUAL="启用劫持并手动指定网段"
VM_DISABLE="禁用劫持"
VM_INPUT_INFO="多个网段请用空格连接可使用【ip route】命令查看例如"
VM_INPUT_NET="请输入自定义网段"
VM_NO_NET_DETECTED="未检测到容器或虚拟机网段,请先运行容器后再运行脚本,或选择手动设置网段!"
VM_INPUT_DESC_1="多个网段请使用空格分隔可通过【ip route】命令查看"
VM_INPUT_DESC_2="例如:"
#inputport
INPUT_PORT="请输入端口号"
# =================================================
# Advanced config
# =================================================
ADV_HTTP_PORT="修改HTTP/SOCKS5端口"
ADV_HTTP_AUTH="设置HTTP/SOCKS5认证"
ADV_REDIR_PORT="修改Redir/Tproxy端口"
ADV_DNS_PORT="修改DNS监听端口"
ADV_PANEL_PORT="修改面板访问端口"
ADV_PANEL_PASS="设置面板访问密码"
ADV_PANEL_PASS_INPUT="请输入面板访问密码输入0删除"
ADV_HOST="自定义本机 Host 地址"
ADV_TABLE="自定义路由表"
# Advanced auth
ADV_AUTH_FORMAT_DESC="格式必须为 \033[32m用户名:密码\033[0m请使用英文冒号分隔"
ADV_AUTH_WARN="请尽量不要使用特殊符号,以避免产生未知错误!"
ADV_AUTH_REMOVE_HINT="输入 0 可删除认证信息"
ADV_AUTH_INPUT="请输入 HTTP / SOCKS5 用户名及密码"
ADV_AUTH_REMOVED="认证信息已移除!"
ADV_AUTH_ENV_CONFLICT="请先禁用本机劫持功能或使用增强模式!"
ADV_AUTH_INVALID="输入格式错误,请重新输入!"
# Host
ADV_HOST_WARN_LAN="如果你的局域网网段不是 192.168.x / 172.16.x / 10.x请务必修改"
ADV_HOST_WARN_CHANGE="设置后如本机 Host 地址发生变化,请务必重新修改!"
ADV_HOST_INPUT="请输入自定义 Host 地址(输入 0 移除)"
ADV_HOST_REMOVED="自定义 Host 地址已移除,请重新运行脚本以自动获取!"
ADV_HOST_INVALID="输入错误,请仔细核对!"
# Routing table
ADV_TABLE_WARN="仅当 Tproxy/Tun/混合模式 下路由表发生冲突时才需要设置!"
ADV_TABLE_INPUT="请输入路由表编号(不清楚请勿修改,建议 102-125"
# =================================================
# IPv6
# =================================================
IPV6_REDIR="IPv6透明路由劫持IPv6流量"
IPV6_DNS="IPv6-DNS解析是否返回IPv6地址"

View File

@@ -0,0 +1,12 @@
COMMON_INPUT="请输入对应数字"
COMMON_INPUT_L="请输入对应字母或数字"
COMMON_BACK="返回上级菜单"
COMMON_SUCCESS="操作成功!"
COMMON_FAILED="操作失败!"
COMMON_UNSET="未设置"
COMMON_MOD="模式"
COMMON_ERR_NUM="请输入正确的数字!"
COMMON_ERR_LETTER="请输入正确的字母或数字!"
COMMON_ERR_INPUT="输入错误,请重新输入!"
COMMON_ERR_CANCEL="操作已取消!"

52
scripts/lang/chs/dns.lang Normal file
View File

@@ -0,0 +1,52 @@
#=====DNS主菜单=====
DNS_CURRENT_MODE="当前DNS运行模式为"
DNS_RESTART_NOTICE="切换模式后需要手动重启服务以生效!"
DNS_MODE_MIX_DESC="CN域名real-ip其它fake-ip分流"
DNS_MODE_ROUTE_DESC="CN域名real-ip其它dns2proxy分流"
DNS_MODE_REDIR_DESC="不安全需搭配第三方DNS服务使用"
DNS_MENU_PROTECT="DNS防泄漏"
DNS_MENU_HOSTS="Hosts优化"
DNS_MENU_ECS="ECS优化"
DNS_MENU_REDIR="DNS劫持端口"
DNS_PROTECT_DESC="——启用时少量网站可能出现连接卡顿"
DNS_HOSTS_DESC="——调用本机hosts并劫持NTP服务"
DNS_ECS_DESC="——解决CDN下载浪费流量等问题"
DNS_REDIR_PORT_DESC="——用于兼容第三方DNS服务"
DNS_FAKEIP_MENU="管理Fake-IP过滤列表"
DNS_ADV_MENU="修改DNS服务器"
DNS_SET_OK="DNS模式已设置为"
DNS_CORE_UNSUPPORTED="当前内核不支持该功能!"
#=====DNS重定向=====
DNS_REDIR_WARN="仅限搭配第三方DNS服务AdGuard、SmartDNS等使用"
DNS_REDIR_HINT="建议第三方DNS上游指向"
DNS_REDIR_NO_SERVICE="该端口未检测到正在运行的DNS服务"
#=====Fake-IP=====
DNS_FAKEIP_DESC="用于解决Fake-IP模式下部分地址或应用无法连接的问题"
DNS_FAKEIP_TIP="脚本已内置大量地址,只需添加出现问题的地址"
DNS_FAKEIP_EXAMPLE="示例格式如下:\na.b.com\n*.b.com\n*.*.b.com"
DNS_FAKEIP_EXIST="已添加的Fake-IP过滤地址"
DNS_FAKEIP_EMPTY="当前尚未添加任何自定义Fake-IP过滤地址"
DNS_FAKEIP_EDIT="输入序号移除,输入地址添加"
#=====DNS高级=====
DNS_ADV_SPLIT="多个DNS地址请使用“|”或“,”分隔输入"
DNS_ADV_CERT="使用DoH/DoT需具备本地根证书文件"
DNS_ADV_SINGBOX_LIMIT="注意SingBox内核仅加载第一个DNS"
DNS_ADV_EDIT_DIRECT="修改DIRECT-DNS"
DNS_ADV_EDIT_PROXY="修改PROXY-DNS该DNS查询会经过节点"
DNS_ADV_EDIT_DEFAULT="修改DEFAULT-DNS必须是IP用于解析其他DNS"
DNS_ADV_AUTO_ENCRYPT="一键配置加密DNS"
DNS_ADV_RESET="重置默认DNS配置"
DNS_IPV6_NOT_SUPPORT="该选项暂不支持IPv6加密DNS"
DNS_ENCRYPT_OK="已设置加密DNS如遇DNS解析问题请重置DNS配置"
DNS_CORE_REQUIRE="请使用Mihomo或SingBox内核"

View File

@@ -0,0 +1,83 @@
# ===== 通用提示 =====
MENU_RESTART_NOTICE="检测到配置变更,是否立即重启服务以应用新配置:"
MENU_PORT_CONFLICT_TITLE="检测到端口被以下进程占用!内核可能无法正常启动!"
MENU_PORT_CONFLICT_HINT="请修改默认端口配置!"
MENU_CORE_LOADED_OK="内核加载完成!"
MENU_CORE_LOADED_BAD="检测到不可用的内核文件可能是文件受损或CPU架构不匹配"
MENU_CORE_REMOVED="内核文件已移除,请认真检查后重新上传!"
MENU_CFG_LOADED_OK="配置文件加载完成!"
MENU_OVERRIDE_WARN="你已经禁用了配置文件覆写功能,这会导致大量脚本功能无法使用!"
MENU_OVERRIDE_ASK="是否取消禁用:"
# ===== 欢迎与状态 =====
MENU_WELCOME="欢迎使用ShellCrash"
MENU_RUN_ON="正在运行"
MENU_RUN_SET="已设置"
MENU_RUN_OFF="没有运行"
MENU_PURE_MOD="纯净"
MENU_MOD="模式"
MENU_IP_DF="设备IP地址"
MENU_AUTOSTART_ON="已设置开机启动!"
MENU_AUTOSTART_OFF="未设置开机启动!"
MENU_AUTOSTART_DEBUG="并处于debug状态"
MENU_MEM_USED="当前内存占用:"
MENU_RUNNING_TIME="已运行:"
MENU_TG_CHANNEL="TG频道"
# ===== /tmp 文件检测 =====
MENU_TMP_CORE_FOUND="发现可用的内核文件:"
MENU_TMP_CORE_ASK="是否立即加载该内核(会停止当前服务):"
MENU_TMP_CFG_FOUND="发现内核配置文件:"
MENU_TMP_CFG_ASK="是否立即加载为配置文件:"
MENU_MAIN_1="启动/重启服务"
MENU_MAIN_2="功能设置"
MENU_MAIN_3="停止服务"
MENU_MAIN_4="启动设置"
MENU_MAIN_5="自动任务"
MENU_MAIN_6="配置文件管理"
MENU_MAIN_7="访问与控制"
MENU_MAIN_8="工具与优化"
MENU_MAIN_9="更新与支持"
MENU_MAIN_0="退出脚本"
MENU_MAIN_PROMPT="请输入对应数字> "
# ===== 服务操作 =====
MENU_SERVICE_STOPPED="服务已停止!"
# ===== 测试 / 调试 =====
MENU_TEST_RUNNING_1="正在测试运行!"
MENU_TEST_RUNNING_2="如发现错误请截图后前往咨询:"
MENU_TEST_DONE_OK="测试完成!没有发现问题,请重新启动服务~"
MENU_TEST_DONE_FAIL="测试完成!"
MENU_TEST_LOG_HINT="完整执行记录请查看:"
MENU_ERROR_FOUND="发现错误:"
# ===== 命令行帮助 =====
MENU_CLI_TEST="测试模式"
MENU_CLI_HELP="帮助列表"
MENU_CLI_UNINSTALL="卸载脚本"
MENU_CLI_INIT="初始化脚本"
MENU_CLI_DEBUG="测试运行"
MENU_CLI_START="启动服务"
MENU_CLI_STOP="停止服务"
MENU_CLI_BOOT_INIT="开机初始化"
MENU_HELP_ONLINE="在线求助:"
MENU_HELP_BLOG="官方博客:"
MENU_HELP_GITHUB="发布页面:"

View File

@@ -0,0 +1,11 @@
# ===== Startup =====
START_SERVICE_OK="Service started successfully!"
START_WEB_HINT="Please use"
START_WEB_HINT2="manage built-in rules"
START_PAC_HINT="Other devices can connect using PAC configuration:"
START_PROXY_HINT="Or connect using HTTP / SOCKS5:"
# ===== Startup Flow =====
START_NO_CORE_CFG_TRY_GEN="Core configuration not found. Attempting to generate providers configuration!"
START_NO_CORE_CFG_IMPORT_FIRST="Core configuration not found. Please import a configuration first!"
START_FIREWALL_DONE="Firewall configuration completed!"

View File

@@ -0,0 +1,128 @@
# =================================================
# Settings main menu
# =================================================
SET_MENU_TITLE="Welcome to the Function Settings Menu:"
SET_MENU_REDIR="Routing Mode:"
SET_MENU_DNS="DNS Settings:"
SET_MENU_FW_FILTER="Transparent Routing Traffic Filter"
SET_MENU_SKIP_CERT="Skip Cert Verify:"
SET_MENU_SNIFFER="Enable Sniff:"
SET_MENU_ADV_PORT="Custom Ports and Secrets"
SET_MENU_IPV6="IPv6 Settings:"
SET_MENU_RESET="Reset / Backup / Restore Script Settings"
SET_MENU_LANG="Language"
SET_MENU_UI="UI Switch"
# =================================================
# Main menu messages
# =================================================
SET_WARN_NONROOT="Non-root users may not be able to configure some modes correctly. Continue anyway?"
SET_SKIP_CERT_ON="Skipping local certificate verification is now ENABLED!"
SET_SKIP_CERT_OFF="Skipping local certificate verification is now DISABLED!"
SET_SNIFFER_CORE_SWITCH="Automatically switched to Meta core (required for domain sniffing)"
SET_SNIFFER_LOCKED="Domain sniffing cannot be disabled with the current core and DNS mode combination!"
SET_CORE_RUNNING="Service is currently running and must be stopped first!"
SET_CORE_STOP_CONFIRM="Do you want to stop the service?"
# =================================================
# Backup / Restore / Reset
# =================================================
SET_BACKUP="Backup Script Settings"
SET_RESTORE="Restore Script Settings"
SET_RESET="Reset Script Settings"
SET_BACKUP_OK="Script settings have been backed up!"
SET_RESTORE_OK="Script settings have been restored! (Overwritten config has been backed up)"
SET_RESET_OK="Script settings have been reset! (Old config has been backed up)"
SET_BACKUP_MISS="Backup file not found. Please back up first!"
SET_NEED_RESTART="Please restart the script for changes to take effect!"
# =================================================
# Redir mode
# =================================================
SET_REDIR_DEFAULT="Redir Mode"
SET_REDIR_CURRENT="Current routing mode:"
SET_CORE_CURRENT="ShellCrash core:"
SET_REDIR_RESTART_HINT="You must manually restart the service for the change to take effect!"
SET_REDIR_APPLIED="Routing mode set to"
SET_REDIR_REDIR="Redir Mode"
SET_REDIR_MIX="Mix Mode"
SET_REDIR_TPROXY="Tproxy Mode"
SET_REDIR_TUN="Tun Mode"
SET_REDIR_REDIRDES="Redirect TCP traffic only (no UDP)"
SET_REDIR_MIXDES="Redirect TCP via Redir, UDP via Tun"
SET_REDIR_TPROXYDES="Tproxy forwards both TCP UDP"
SET_REDIR_TUNDES="Tun forwards both TCP UDP (high resource usage)"
SET_NO_MOD="The kernel module not detected"
SET_NO_MOD2="Please install required dependencies or select another mode!"
XIAOMI_QOS="Xiaomi QoS service conflicts with the current mode. Disable related features?"
# =================================================
# Firewall / VM
# =================================================
SET_FW_AREA="Set Routing Hijack Scope"
SET_VM_REDIR="Container / VM Hijacking"
SET_FW_SWITCH="Switch Firewall Backend"
SET_FW_AREA_DESC="LAN only|Local only|LAN&Local|Pure mode|Bypass:"
FW_AREA_NOTE="If you are using a third-party DNS like SmartDNS, \ndo not enable local hijacking or run the service as a ShellCrash user"
FW_AREA_LAN="Hijack LAN traffic only"
FW_AREA_LOCAL="Hijack local device traffic only"
FW_AREA_BOTH="Hijack both LAN and local device traffic"
FW_AREA_NONE="Do not hijack traffic (Pure mode)"
FW_NO_NFTABLES="nftables is not installed, or the version is too old (< 1.0.2). Unable to switch!"
FW_NO_IPTABLES="iptables is not installed. Unable to switch!"
FW_NO_FIREWALL_BACKEND="No available firewall backend detected (iptables / nftables). Unable to switch!"
VM_DETECT_DESC="Default Container/VM Subnet:"
VM_ENABLE_AUTO="Enable hijacking using automatically detected subnets"
VM_ENABLE_MANUAL="Enable hijacking and manually specify subnets"
VM_DISABLE="Disable hijacking"
VM_INPUT_INFO="Separate multiple segments with spaces. Check your configuration using ip route. Example:"
VM_INPUT_NET="Please enter cust subnets"
VM_NO_NET_DETECTED="No container or VM subnet detected. Please start the container first, or configure the subnet manually!"
VM_INPUT_DESC="Multiple subnets should be separated by spaces. You can check them using the 'ip route' command, for example:"
#inputport
INPUT_PORT="Input port"
# =================================================
# Advanced config
# =================================================
ADV_HTTP_PORT="Change HTTP / SOCKS5 Port"
ADV_HTTP_AUTH="Set HTTP / SOCKS5 Authentication"
ADV_REDIR_PORT="Change Redir / Tproxy Ports"
ADV_DNS_PORT="Change DNS Listening Port"
ADV_PANEL_PORT="Change Web Panel Port"
ADV_PANEL_PASS="Set Web Panel Password"
ADV_PANEL_PASS_INPUT="Enter web panel password (enter 0 to remove)"
ADV_HOST="Custom Local Host Address"
ADV_TABLE="Custom Routing Table"
# Advanced auth
ADV_AUTH_FORMAT_DESC="Format must be \033[32musername:password\033[0m, separated by a colon!"
ADV_AUTH_WARN="Avoid using special characters to prevent unexpected issues!"
ADV_AUTH_REMOVE_HINT="Enter 0 to remove authentication"
ADV_AUTH_INPUT="Please enter HTTP / SOCKS5 username and password"
ADV_AUTH_REMOVED="Authentication information has been removed!"
ADV_AUTH_ENV_CONFLICT="Please disable local hijacking or switch to enhanced mode first!"
ADV_AUTH_INVALID="Invalid input format. Please try again!"
# Host
ADV_HOST_WARN_LAN="If your LAN subnet is not 192.168.x / 172.16.x / 10.x, you must modify it!"
ADV_HOST_WARN_CHANGE="If the local host address changes after setting, please update it again!"
ADV_HOST_INPUT="Please enter a custom host address (enter 0 to remove)"
ADV_HOST_REMOVED="Custom host address removed. Please rerun the script to auto-detect!"
ADV_HOST_INVALID="Invalid input. Please check carefully!"
# Routing table
ADV_TABLE_WARN="Only required when routing table conflicts occur in Tproxy, Tun, or Mixed mode!"
ADV_TABLE_INPUT="Please enter the routing table ID (do not modify unless necessary, recommended 102-125)"
# =================================================
# IPv6
# =================================================
IPV6_REDIR="IPv6 Transparent Routing (Hijack IPv6 Traffic)"
IPV6_DNS="IPv6 DNS Resolution (Return IPv6 addresses)"

View File

@@ -0,0 +1,12 @@
COMMON_INPUT="Please enter a number"
COMMON_INPUT_L="Enter a letter or a number"
COMMON_BACK="Back"
COMMON_SUCCESS="Setup Success!"
COMMON_FAILED="Setup failed!"
COMMON_UNSET="Not set"
COMMON_MOD="Mod"
COMMON_ERR_NUM="Please enter a valid number!"
COMMON_ERR_LETTER="Please enter a valid letter or number!"
COMMON_ERR_INPUT="Invalid input, please try again!"
COMMON_ERR_CANCEL="Operation cancelled!"

54
scripts/lang/en/dns.lang Normal file
View File

@@ -0,0 +1,54 @@
#===== DNS Main Menu =====
DNS_CURRENT_MODE="Current DNS running mode:"
DNS_RESTART_NOTICE="Changes require a manual service restart to take effect."
DNS_MODE_MIX_DESC="CN domains use real-ip, others use fake-ip routing"
DNS_MODE_ROUTE_DESC="CN domains use real-ip, others use dns2proxy routing"
DNS_MODE_REDIR_DESC="Insecure. Must be used with a third-party DNS service."
DNS_MENU_PROTECT="DNS Leak Protect"
DNS_MENU_HOSTS="Hosts Optimization"
DNS_MENU_ECS="ECS Optimization"
DNS_MENU_REDIR="DNS Redirect Port"
DNS_PROTECT_DESC="May cause slow connections on some websites when enabled"
DNS_HOSTS_DESC="Use local hosts file and hijack NTP service"
DNS_ECS_DESC="Reduce wasted traffic caused by CDN misrouting"
DNS_REDIR_PORT_DESC="Used for compatibility with third-party DNS services"
DNS_FAKEIP_MENU="Manage Fake-IP Filter List"
DNS_ADV_MENU="Configure DNS Servers"
DNS_SET_OK="DNS mode has been set to"
DNS_CORE_UNSUPPORTED="The current core does not support this feature."
#===== DNS Redirect =====
DNS_REDIR_WARN="For use with third-party DNS services only (AdGuard, SmartDNS, etc.)"
DNS_REDIR_HINT="It is recommended to set the upstream DNS of the third-party service to"
DNS_REDIR_INPUT="Enter the listening port of the third-party DNS service (0 to reset)>"
DNS_REDIR_NO_SERVICE="No running DNS service detected on this port!"
#===== Fake-IP =====
DNS_FAKEIP_DESC="Used to resolve connectivity issues for certain addresses or applications in Fake-IP mode"
DNS_FAKEIP_TIP="The script already includes many built-in entries. Only add problematic addresses."
DNS_FAKEIP_EXAMPLE="Examples:\na.b.com\n*.b.com\n*.*.b.com"
DNS_FAKEIP_EXIST="Existing Fake-IP filter entries:"
DNS_FAKEIP_EMPTY="No Fake-IP filter entries have been added"
DNS_FAKEIP_EDIT="Enter a number to remove an entry, or enter an address to add one"
#===== Advanced DNS =====
DNS_ADV_SPLIT="Use '|' or ',' to separate multiple DNS addresses"
DNS_ADV_CERT="DoH/DoT requires a local root certificate file"
DNS_ADV_SINGBOX_LIMIT="Note: SingBox core only loads the first DNS entry"
DNS_ADV_EDIT_DIRECT="Edit DIRECT-DNS"
DNS_ADV_EDIT_PROXY="Edit PROXY-DNS (queries go through the proxy)"
DNS_ADV_EDIT_DEFAULT="Edit DEFAULT-DNS (must be an IP, used to resolve other DNS servers)"
DNS_ADV_AUTO_ENCRYPT="Auto-configure Encrypted DNS"
DNS_ADV_RESET="Reset to default DNS configuration"
DNS_INPUT_NEW="Enter new DNS address>"
DNS_IPV6_NOT_SUPPORT="This option does not support IPv6 encrypted DNS!"
DNS_ENCRYPT_OK="Encrypted DNS has been configured. If DNS issues occur, please reset DNS settings."
DNS_CORE_REQUIRE="Please use the Mihomo or SingBox core"

83
scripts/lang/en/menu.lang Normal file
View File

@@ -0,0 +1,83 @@
# ===== Common Prompts =====
MENU_RESTART_NOTICE="Changes have been detected. Please restart the service!"
MENU_PORT_CONFLICT_TITLE="The port is occupied by the following process. The core may fail to start!"
MENU_PORT_CONFLICT_HINT="Please modify the default port configuration!"
MENU_CORE_LOADED_OK="Core loaded successfully!"
MENU_CORE_LOADED_BAD="The core file is invalid. It may be corrupted or incompatible with the CPU architecture!"
MENU_CORE_REMOVED="The core file has been removed. Please verify and upload it again!"
MENU_CFG_LOADED_OK="Configuration file loaded successfully!"
MENU_OVERRIDE_WARN="You have disabled configuration overwrite. This will cause many features to be unavailable!"
MENU_OVERRIDE_ASK="Cancel the disable setting?"
# ===== Welcome & Status =====
MENU_WELCOME="Welcome to ShellCrash!"
MENU_RUN_ON=" Running"
MENU_RUN_SET="Configured"
MENU_RUN_OFF="Stopped"
MENU_PURE_MOD="Pure"
MENU_MOD=" Mod"
MENU_IP_DF="Device IP Address"
MENU_AUTOSTART_ON="Autostart enable!"
MENU_AUTOSTART_OFF="Autostart disable!"
MENU_AUTOSTART_DEBUG="Debug mode!"
MENU_MEM_USED="Memory usage: "
MENU_RUNNING_TIME="Running time: "
MENU_TG_CHANNEL="Telegram Channel: "
# ===== /tmp File Detection =====
MENU_TMP_CORE_FOUND="Available core file found:"
MENU_TMP_CORE_ASK="Load this core file? (The current service will be stopped)"
MENU_TMP_CFG_FOUND="Kernel configuration file found:"
MENU_TMP_CFG_ASK="Load as the configuration file? (1/0) > "
# ===== Main Menu =====
MENU_MAIN_1="Start / Restart Service"
MENU_MAIN_2="Feature Settings"
MENU_MAIN_3="Stop Service"
MENU_MAIN_4="Startup Settings"
MENU_MAIN_5="Scheduled Tasks"
MENU_MAIN_6="Configuration Management"
MENU_MAIN_7="Access & Control"
MENU_MAIN_8="Tools & Optimization"
MENU_MAIN_9="Updates & Support"
MENU_MAIN_0="Exit Script"
MENU_MAIN_PROMPT="Please enter a number > "
# ===== Service Operations =====
MENU_SERVICE_STOPPED="Service has been stopped!"
# ===== Test / Debug =====
MENU_TEST_RUNNING="Running test mode. If errors occur, please take a screenshot and seek assistance."
MENU_TEST_DONE_OK="Test completed! No issues found. Please restart the service."
MENU_TEST_DONE_FAIL="Test completed!"
MENU_TEST_LOG_HINT="Full execution log can be found at:"
MENU_ERROR_FOUND="Error found:"
# ===== Command Line Help =====
MENU_CLI_TEST="Test Mode"
MENU_CLI_HELP="Help List"
MENU_CLI_UNINSTALL="Uninstall Script"
MENU_CLI_INIT="Initialize Script"
MENU_CLI_DEBUG="Debug Mode"
MENU_CLI_START="Start Service"
MENU_CLI_STOP="Stop Service"
MENU_CLI_BOOT_INIT="Boot Initialization"
MENU_HELP_ONLINE="Online Support:"
MENU_HELP_BLOG="Official Blog:"
MENU_HELP_GITHUB="Release Page:"

11
scripts/libs/README.md Normal file
View File

@@ -0,0 +1,11 @@
用于存放脚本内置工具的脚本
引用方式必须为:
```shell
. "$CRASHDIR"/libs/xxx.sh
```
返回码必须是return x而不能是exit x
此处脚本内容不应包含文字输出和log输出

View File

@@ -0,0 +1,16 @@
check_autostart(){
if [ "$start_old" = ON ];then
[ ! -f "$CRASHDIR"/.dis_startup ] && return 0
elif [ -f /etc/rc.common -a "$(cat /proc/1/comm)" = "procd" ]; then
[ -n "$(find /etc/rc.d -name '*shellcrash')" ] && return 0
elif ckcmd systemctl; then
[ "$(systemctl is-enabled shellcrash.service 2>&1)" = enabled ] && return 0
elif grep -q 's6' /proc/1/comm; then
[ -f /etc/s6-overlay/s6-rc.d/user/contents.d/afstart ] && return 0
elif rc-status -r >/dev/null 2>&1; then
rc-update show default | grep -q "shellcrash" && return 0
else
return 1
fi
return 1
}

View File

@@ -0,0 +1,7 @@
ckcmd() {
if command -v sh >/dev/null 2>&1;then
command -v "$1" >/dev/null 2>&1
else
type "$1" >/dev/null 2>&1
fi
}

View File

@@ -0,0 +1,14 @@
check_cpucore(){ #自动获取内核架构
cputype=$(uname -ms | tr ' ' '_' | tr '[A-Z]' '[a-z]')
[ -n "$(echo $cputype | grep -E "linux.*armv.*")" ] && cpucore="armv5"
[ -n "$(echo $cputype | grep -E "linux.*armv7.*")" ] && [ -n "$(cat /proc/cpuinfo | grep vfp)" ] && [ ! -d /jffs ] && cpucore="armv7"
[ -n "$(echo $cputype | grep -E "linux.*aarch64.*|linux.*armv8.*")" ] && cpucore="arm64"
[ -n "$(echo $cputype | grep -E "linux.*86.*")" ] && cpucore="386"
[ -n "$(echo $cputype | grep -E "linux.*86_64.*")" ] && cpucore="amd64"
if [ -n "$(echo $cputype | grep -E "linux.*mips.*")" ];then
mipstype=$(echo -n I | hexdump -o 2>/dev/null | awk '{ print substr($2,6,1); exit}') #通过判断大小端判断mips或mipsle
[ "$mipstype" = "0" ] && cpucore="mips-softfloat" || cpucore="mipsle-softfloat"
fi
[ -n "$cpucore" ] && setconfig cpucore $cpucore
}

View File

@@ -0,0 +1,5 @@
#检查目录剩余空间——$1:目标路径 $2:-h参数
dir_avail() {
df -h >/dev/null 2>&1 && h="$2"
df -P $h "${1:-.}" 2>/dev/null | awk 'NR==2 {print $4}'
}

View File

@@ -0,0 +1,8 @@
if echo "$crashcore" | grep -q 'singbox'; then
target=singbox
format=json
else
target=clash
format=yaml
fi
core_config="$CRASHDIR/${format}s/config.$format"

10
scripts/libs/compare.sh Normal file
View File

@@ -0,0 +1,10 @@
compare() { #对比文件
if [ ! -f "$1" ] || [ ! -f "$2" ]; then
return 1
elif ckcmd cmp; then
cmp -s "$1" "$2"
return $?
else
[ "$(cat "$1")" = "$(cat "$2")" ] && return 0 || return 1
fi
}

View File

@@ -0,0 +1,79 @@
[ -n "$(find --help 2>&1 | grep -o size)" ] && find_para=' -size +2000' #find命令兼容
core_unzip() { #$1:需要解压的文件 $2:目标文件名
if echo "$1" |grep -q 'tar.gz$' ;then
[ "$BINDIR" = "$TMPDIR" ] && rm -rf "$TMPDIR"/CrashCore #小闪存模式防止空间不足
[ -n "$(tar --help 2>&1 | grep -o 'no-same-owner')" ] && tar_para='--no-same-owner' #tar命令兼容
mkdir -p "$TMPDIR"/core_tmp
tar -zxf "$1" ${tar_para} -C "$TMPDIR"/core_tmp/
for file in $(find "$TMPDIR"/core_tmp $find_para 2>/dev/null); do
[ -f "$file" ] && [ -n "$(echo $file | sed 's#.*/##' | grep -iE '(CrashCore|sing|meta|mihomo|clash|pre)')" ] && mv -f "$file" "$TMPDIR"/"$2"
done
rm -rf "$TMPDIR"/core_tmp
elif echo "$1" |grep -q '.gz$' ;then
gunzip -c "$1" > "$TMPDIR"/"$2"
elif echo "$1" |grep -q '.upx$' ;then
ln -sf "$1" "$TMPDIR"/"$2"
else
mv -f "$1" "$TMPDIR"/"$2"
fi
chmod +x "$TMPDIR"/"$2"
}
core_find(){
if [ ! -f "$TMPDIR"/CrashCore ];then
core_dir=$(find "$BINDIR"/CrashCore.* $find_para 2>/dev/null)
[ -n "$core_dir" ] && core_unzip "$core_dir" CrashCore
fi
}
core_check(){
[ -n "$(pidof CrashCore)" ] && "$CRASHDIR"/start.sh stop #停止内核服务防止内存不足
core_unzip "$1" core_new
sbcheck=$(echo "$crashcore" | grep 'singbox')
v=''
if [ -n "$sbcheck" ] && "$TMPDIR"/core_new -h 2>&1 | grep -q 'sing-box'; then
v=$("$TMPDIR"/core_new version 2>/dev/null | grep version | awk '{print $3}')
COMMAND='"$TMPDIR/CrashCore run -D $BINDIR -C $TMPDIR/jsons"'
elif [ -z "$sbcheck" ] && "$TMPDIR"/core_new -h 2>&1 | grep -q '\-t';then
v=$("$TMPDIR"/core_new -v 2>/dev/null | head -n 1 | sed 's/ linux.*//;s/.* //')
COMMAND='"$TMPDIR/CrashCore -d $BINDIR -f $TMPDIR/config.yaml"'
fi
if [ -z "$v" ]; then
rm -rf "$1" "$TMPDIR"/core_new
return 2
else
rm -f "$BINDIR"/CrashCore.tar.gz "$BINDIR"/CrashCore.gz "$BINDIR"/CrashCore.upx
if [ -z "$zip_type" ];then
gzip -c "$TMPDIR/core_new" > "$BINDIR/CrashCore.gz"
else
mv -f "$1" "$BINDIR/CrashCore.$zip_type"
fi
mv -f "$TMPDIR/core_new" "$TMPDIR/CrashCore"
core_v="$v"
setconfig COMMAND "$COMMAND" "$CRASHDIR"/configs/command.env && . "$CRASHDIR"/configs/command.env
setconfig crashcore "$crashcore"
setconfig core_v "$core_v"
setconfig custcorelink "$custcorelink"
return 0
fi
}
core_webget(){
. "$CRASHDIR"/libs/web_get_bin.sh
. "$CRASHDIR"/libs/check_target.sh
if [ -z "$custcorelink" ];then
[ -z "$zip_type" ] && zip_type='tar.gz'
get_bin "$TMPDIR/Coretmp.$zip_type" "bin/$crashcore/${target}-linux-${cpucore}.$zip_type"
else
zip_type=$(echo "$custcorelink" | grep -oE 'tar.gz$')
[ -z "$zip_type" ] && zip_type=$(echo "$custcorelink" | grep -oE 'gz$')
[ -n "$zip_type" ] && webget "$TMPDIR/Coretmp.$zip_type" "$custcorelink"
fi
#校验内核
if [ "$?" = 0 ];then
core_check "$TMPDIR/Coretmp.$zip_type"
else
rm -rf "$TMPDIR/Coretmp.$zip_type"
return 1
fi
}

View File

@@ -0,0 +1,26 @@
#生成指定位数的加密秘钥符合ss2022协议
gen_random() {
if ckcmd openssl;then
openssl rand --base64 "$1"
elif ckcmd base64;then
head -c "$1" /dev/urandom | base64 | tr -d '\n'
elif busybox base64 --help >/dev/null 2>&1;then
head -c "$1" /dev/urandom | base64 | tr -d '\n'
elif ckcmd uuencode;then
head -c "$1" /dev/urandom | uuencode -m - | sed -n '2p'
else
return 1
fi
}
#对指定字符串进行base64转码
gen_base64() {
if ckcmd base64;then
echo -n "$1" | base64 | tr -d '\n'
elif busybox base64 --help >/dev/null 2>&1;then
echo -n "$1" | busybox base64 | tr -d '\n'
elif ckcmd openssl;then
echo -n "$1" | openssl base64 -A
else
return 1
fi
}

View File

@@ -0,0 +1,22 @@
# 检查配置文件
[ -f "$CRASHDIR"/configs/ShellCrash.cfg ] || . "$CRASHDIR"/init.sh >/dev/null 2>&1
. "$CRASHDIR"/configs/command.env >/dev/null 2>&1
. "$CRASHDIR"/configs/ShellCrash.cfg
[ -z "$mix_port" ] && mix_port=7890
[ -z "$redir_port" ] && redir_port=7892
[ -z "$tproxy_port" ] && tproxy_port=7893
[ -z "$db_port" ] && db_port=9999
[ -z "$dns_port" ] && dns_port=1053
[ -z "$dns_redir_port" ] && dns_redir_port="$dns_port"
[ -z "$fwmark" ] && fwmark="$redir_port"
routing_mark=$((fwmark + 2))
[ -z "$table" ] && table=100
[ -z "$dns_nameserver" ] && {
dns_nameserver='223.5.5.5, 1.2.4.8'
cat /proc/net/udp | grep -q '0035' && dns_nameserver='127.0.0.1'
}
[ -z "$dns_fallback" ] && dns_fallback="1.1.1.1, 8.8.8.8"
[ -z "$dns_resolver" ] && dns_resolver="223.5.5.5, 2400:3200::1"

15
scripts/libs/get_ecsip.sh Normal file
View File

@@ -0,0 +1,15 @@
get_ecs_address() {
for f in /tmp/resolv.conf.auto /tmp/resolv.conf /tmp/resolv.conf.d/resolv.conf.auto; do
[ -f "$f" ] || continue
ip=$(grep -A1 "^# Interface wan$" "$f" | grep nameserver | awk '{printf "%s ", $2}')
[ -n "$ip" ] && return
done
. "$CRASHDIR"/libs/web_get_lite.sh
for web in http://members.3322.org/dyndns/getip http://4.ipw.cn http://ipinfo.io/ip; do
ip=$(web_get_lite "$web" 0)
[ -n "$ip" ] && return
done
}
get_ecs_address
[ -n "$ip" ] && ecs_address="${ip%.*}.0/24"

8
scripts/libs/i18n.sh Normal file
View File

@@ -0,0 +1,8 @@
load_lang() {
i18n=$(cat "$CRASHDIR"/configs/i18n.cfg 2>/dev/null)
[ -z "$i18n" ] && i18n=chs
file="$CRASHDIR/lang/$i18n/$1.lang"
[ -s "$file" ] && . "$file"
}

54
scripts/libs/logger.sh Normal file
View File

@@ -0,0 +1,54 @@
[ -n "$__IS_LIB_LOGGER" ] && return
__IS_LIB_LOGGER=1
#日志工具
. "$CRASHDIR"/libs/web_json.sh
#$1日志内容$2显示颜色$3是否推送
logger() {
TMPDIR=/tmp/ShellCrash
[ -n "$2" -a "$2" != 0 ] && printf "\033[%sm%s\033[0m\n" "$2" "$1"
log_text="$(date "+%G-%m-%d_%H:%M:%S")~$1"
echo "$log_text" >>"$TMPDIR"/ShellCrash.log
[ "$(wc -l "$TMPDIR"/ShellCrash.log | awk '{print $1}')" -gt 199 ] && sed -i '1,20d' "$TMPDIR"/ShellCrash.log
#推送远程日志
[ -z "$3" ] && {
[ -n "$device_name" ] && log_text="$log_text($device_name)"
[ -n "$push_TG" ] && {
url="https://api.telegram.org/bot${push_TG}/sendMessage"
[ "$push_TG" = 'publictoken' ] && url='https://tgbot.jwsc.eu.org/publictoken/sendMessage'
content="{\"chat_id\":\"${chat_ID}\",\"text\":\"$log_text\"}"
web_json_post "$url" "$content" &
}
[ -n "$push_bark" ] && {
url="${push_bark}"
content="{\"body\":\"${log_text}\",\"title\":\"ShellCrash_log\",\"level\":\"passive\",\"badge\":\"1\"}"
web_json_post "$url" "$content" &
}
[ -n "$push_Deer" ] && {
url="https://api2.pushdeer.com/message/push"
content="{\"pushkey\":\"${push_Deer}\",\"text\":\"$log_text\"}"
web_json_post "$url" "$content" &
}
[ -n "$push_Po" ] && {
url="https://api.pushover.net/1/messages.json"
content="{\"token\":\"${push_Po}\",\"user\":\"${push_Po_key}\",\"title\":\"ShellCrash_log\",\"message\":\"$log_text\"}"
web_json_post "$url" "$content" &
}
[ -n "$push_PP" ] && {
url="http://www.pushplus.plus/send"
content="{\"token\":\"${push_PP}\",\"title\":\"ShellCrash_log\",\"content\":\"$log_text\"}"
web_json_post "$url" "$content" &
}
[ -n "$push_Gotify" ] && {
url="${push_Gotify}"
content="{\"title\":\"ShellCrash_log\",\"message\":\"$log_text\",\"priority\":5}"
web_json_post "$url" "$content" &
}
[ -n "$push_SynoChat" ] && {
url="${push_ChatURL}/webapi/entry.cgi?api=SYNO.Chat.External&method=chatbot&version=2&token=${push_ChatTOKEN}"
content="payload={\"text\":\"${log_text}\", \"user_ids\":[${push_ChatUSERID}]}"
web_json_post "$url" "$content" &
}
} &
}

View File

@@ -0,0 +1,28 @@
#!/bin/sh
# Copyright (C) Juewuy
#meta内核vmess入站生成
[ "$vms_service" = ON ] && {
cat >>"$TMPDIR"/listeners.yaml <<EOF
- name: "vmess-in"
type: vmess
port: $vms_port
listen:
users:
- uuid: $vms_uuid
alterId: 0
ws-path: $vms_ws_path
EOF
}
#meta内核ss入站生成
[ "$sss_service" = ON ] && {
cat >>"$TMPDIR"/listeners.yaml <<EOF
- name: "ss-in"
type: shadowsocks
port: $sss_port
listen:
cipher: $sss_cipher
password: $sss_pwd
udp: true
EOF
}

View File

@@ -0,0 +1,54 @@
#!/bin/sh
# Copyright (C) Juewuy
[ "$ts_service" = ON ] && ! grep -q '"tailscale"' "$CRASHDIR"/jsons/endpoints.json 2>/dev/null && {
[ "$ts_subnet" = true ] && {
. "$CRASHDIR"/starts/fw_getlanip.sh && getlanip
advertise_routes=$(echo "$host_ipv4"|sed 's/[[:space:]]\+/", "/g; s/^/"/; s/$/"/')
}
[ -z "$ts_exit_node" ] && ts_exit_node=false
[ -z "$ts_hostname" ] && ts_hostname='ShellCrash'
cat >"$TMPDIR"/jsons/tailscale.json <<EOF
{
"endpoints": [
{
"type": "tailscale",
"tag": "ts-ep",
"state_directory": "$CRASHDIR/tailscale",
"auth_key": "$ts_auth_key",
"hostname": "$ts_hostname",
"advertise_routes": [$advertise_routes],
"advertise_exit_node": $ts_exit_node,
"udp_timeout": "5m"
}
]
}
EOF
}
[ "$wg_service" = ON ] && ! grep -q '"wireguard"' "$CRASHDIR"/jsons/endpoints.json 2>/dev/null && {
[ -n "$wg_ipv6" ] && wg_ipv6_add=", \"$wg_ipv6\""
cat >"$TMPDIR"/jsons/wireguard.json <<EOF
{
"endpoints": [
{
"type": "wireguard",
"tag": "wg-ep",
"system": true,
"mtu": 1420,
"address": [ "$wg_ipv4"$wg_ipv6_add ],
"private_key": "$wg_private_key",
"peers": [
{
"address": "$wg_server",
"port": $wg_port,
"public_key": "$wg_public_key",
"pre_shared_key": "$wg_pre_shared_key",
"allowed_ips": ["0.0.0.0/0", "::/0"]
}
]
}
]
}
EOF
}

View File

@@ -0,0 +1,40 @@
#!/bin/sh
# Copyright (C) Juewuy
[ "$vms_service" = ON ] && {
[ -n "$vms_ws_path" ] && transport=', "transport": { "type": "ws", "path": "'"$vms_ws_path"'" }'
cat >"$TMPDIR"/jsons/vmess-in.json <<EOF
{
"inbounds": [
{
"type": "vmess",
"tag": "vmess-in",
"listen": "::",
"listen_port": $vms_port,
"users": [
{
"uuid": "$vms_uuid"
}
]$transport
}
]
}
EOF
}
[ "$sss_service" = ON ] && {
cat >"$TMPDIR"/jsons/ss-in.json <<EOF
{
"inbounds": [
{
"type": "shadowsocks",
"tag": "ss-in",
"listen": "::",
"listen_port": $sss_port,
"method": "$sss_cipher",
"password": "$sss_pwd",
}
]
}
EOF
}

View File

@@ -0,0 +1,6 @@
#参数1代表变量名参数2代表变量值,参数3即文件路径
setconfig() {
[ -z "$3" ] && configpath="$CRASHDIR"/configs/ShellCrash.cfg || configpath="${3}"
sed -i "/^${1}=.*/d" "$configpath"
printf '%s=%s\n' "$1" "$2" >>"$configpath"
}

27
scripts/libs/set_cron.sh Normal file
View File

@@ -0,0 +1,27 @@
crondir="$(crond -h 2>&1 | grep -oE 'Default:.*' | awk -F ":" '{print $2}')"
[ ! -w "$crondir" ] && crondir="/etc/storage/cron/crontabs"
[ ! -w "$crondir" ] && crondir="/var/spool/cron/crontabs"
[ ! -w "$crondir" ] && crondir="/var/spool/cron"
tmpcron="$TMPDIR"/cron_tmp
croncmd() { #定时任务工具
if [ -n "$(crontab -h 2>&1 | grep '\-l')" ]; then
crontab "$1"
elif [ -w "$crondir" ] && [ -n "$USER" ];then
[ "$1" = "-l" ] && cat "$crondir"/"$USER" 2>/dev/null
[ -f "$1" ] && cat "$1" >"$crondir"/"$USER"
killall -HUP crond 2>/dev/null
else
echo "找不到可用的crond或者crontab应用No available crond or crontab application can be found!"
fi
}
cronset() { #定时任务设置
# 参数1代表要移除的关键字,参数2代表要添加的任务语句
croncmd -l >"$tmpcron"
sed -i "/$1/d" "$tmpcron"
sed -i '/^$/d' "$tmpcron"
echo "$2" >>"$tmpcron"
croncmd "$tmpcron"
rm -f "$tmpcron"
}

View File

@@ -0,0 +1,8 @@
set_profile() {
[ -z "$my_alias" ] && my_alias=crash
sed -i "/ShellCrash\/menu.sh/"d "$1"
echo "alias ${my_alias}=\"$shtype $CRASHDIR/menu.sh\"" >>"$1" #设置快捷命令环境变量
sed -i '/export CRASHDIR=*/'d "$1"
echo "export CRASHDIR=\"$CRASHDIR\"" >>"$1" #设置路径环境变量
}

View File

@@ -0,0 +1,9 @@
setproxy(){
[ -n "$(pidof CrashCore)" ] && {
[ -n "$authentication" ] && auth="$authentication@" || auth=""
[ -z "$mix_port" ] && mix_port=7890
export https_proxy="http://${auth}127.0.0.1:$mix_port"
export http_proxy="http://${auth}127.0.0.1:$mix_port"
}
}

View File

@@ -0,0 +1,10 @@
i=1
while [ -z "$test" -a "$i" -lt 30 ]; do
sleep 1
if curl --version >/dev/null 2>&1; then
test=$(curl -s -H "Authorization: Bearer $secret" http://127.0.0.1:${db_port}/proxies | grep -o proxies)
else
test=$(wget -q --header="Authorization: Bearer $secret" -O - http://127.0.0.1:${db_port}/proxies | grep -o proxies)
fi
i=$((i + 1))
done

15
scripts/libs/urlencode.sh Normal file
View File

@@ -0,0 +1,15 @@
urlencode() {
LC_ALL=C
printf '%s' "$1" \
| hexdump -v -e '/1 "%02X\n"' \
| while read -r hex; do
case "$hex" in
2D|2E|5F|7E|3[0-9]|4[1-9A-F]|5[0-9A]|6[1-9A-F]|7[0-9A-E])
printf "\\$(printf '%03o' "0x$hex")"
;;
*)
printf "%%%s" "$hex"
;;
esac
done
}

49
scripts/libs/web_get.sh Normal file
View File

@@ -0,0 +1,49 @@
. "$CRASHDIR"/libs/set_proxy.sh
webget(){
if pidof CrashCore >/dev/null; then
setproxy #设置临时代理
url=$(printf '%s\n' "$2" |
sed -e 's#https://.*jsdelivr.net/gh/juewuy/ShellCrash[@|/]#https://raw.githubusercontent.com/juewuy/ShellCrash/#' \
-e 's#https://gh.jwsc.eu.org/#https://raw.githubusercontent.com/juewuy/ShellCrash/#')
else
url=$(printf '%s\n' "$2" |
sed 's#https://raw.githubusercontent.com/juewuy/ShellCrash/#https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@#')
fi
#参数【$1】代表下载目录【$2】代表在线地址
#参数【$3】代表输出显示【$4】不启用重定向
#参数【$5】代表验证证书【$6】使用自定义UA
[ -n "$6" ] && agent="--user-agent \"$6\""
if wget --help 2>&1 | grep -q 'show-progress' >/dev/null 2>&1; then
[ "$3" = "echooff" ] && progress='-q' || progress='-q --show-progress'
[ "$4" = "rediroff" ] && redirect='--max-redirect=0' || redirect=''
[ "$5" = "skipceroff" ] && certificate='' || certificate='--no-check-certificate'
wget -Y on $agent $progress $redirect $certificate --timeout=3 -O "$1" "$url" && return 0 #成功则退出否则重试
wget -Y off $agent $progress $redirect $certificate --timeout=5 -O "$1" "$2"
return $?
elif curl --version >/dev/null 2>&1; then
[ "$3" = "echooff" ] && progress='-s' || progress='-#'
[ "$4" = "rediroff" ] && redirect='' || redirect='-L'
[ "$5" = "skipceroff" ] && certificate='' || certificate='-k'
if curl --version | grep -q '^curl 8.' && ckcmd base64; then
auth_b64=$(printf '%s' "$authentication" | base64)
result=$(curl $agent -w '%{http_code}' --connect-timeout 3 --proxy-header "Proxy-Authorization: Basic $auth_b64" $progress $redirect $certificate -o "$1" "$url")
else
result=$(curl $agent -w '%{http_code}' --connect-timeout 3 $progress $redirect $certificate -o "$1" "$url")
fi
[ "$result" = "200" ] && return 0 #成功则退出否则重试
export https_proxy=""
export http_proxy=""
result=$(curl $agent -w '%{http_code}' --connect-timeout 5 $progress $redirect $certificate -o "$1" "$2")
[ "$result" = "200" ]
return $?
elif ckcmd wget;then
[ "$3" = "echooff" ] && progress='-q'
wget -Y on $progress -O "$1" "$url" && return 0 #成功则退出否则重试
wget -Y off $progress -O "$1" "$2"
return $?
else
echo "No Curl or Wget"
return 1
fi
}

View File

@@ -0,0 +1,18 @@
. "$CRASHDIR"/libs/web_get.sh
get_bin() { #专用于项目内部文件的下载
[ -z "$update_url" ] && update_url=https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master
if [ -n "$url_id" ]; then
[ -n "$release_type" ] && rt="$release_type" || rt=master
echo "$2" | grep -q '^bin/' && rt=update #/bin文件改为在update分支下载
echo "$2" | grep -qE '^public/|^rules/' && rt=dev #/public和/rules文件改为在dev分支下载
if [ "$url_id" = 101 -o "$url_id" = 104 ]; then
bin_url="$(grep "$url_id" "$CRASHDIR"/configs/servers.list | awk '{print $3}')@$rt/$2" #jsdelivr特殊处理
else
bin_url="$(grep "$url_id" "$CRASHDIR"/configs/servers.list | awk '{print $3}')/$rt/$2"
fi
else
bin_url="$update_url/$2"
fi
webget "$1" "$bin_url" "$3" "$4" "$5" "$6"
}

View File

@@ -0,0 +1,10 @@
. "$CRASHDIR"/libs/set_proxy.sh
#$1:目标地址 $2:禁用proxy
web_get_lite() {
[ -z "$2" ] && setproxy
if curl --version >/dev/null 2>&1; then
curl -ksSl --connect-timeout 3 "$1" 2>/dev/null
else
wget -Y on -q --timeout=3 -O - "$1"
fi
}

10
scripts/libs/web_json.sh Normal file
View File

@@ -0,0 +1,10 @@
. "$CRASHDIR"/libs/set_proxy.sh
#$1:目标地址 $2:json字符串
web_json_post() {
setproxy
if curl --version >/dev/null 2>&1; then
curl -kfsSl -X POST --connect-timeout 3 -H "Content-Type: application/json" "$1" -d "$2" >/dev/null 2>&1
else
wget -Y on -q --timeout=3 --method=POST --header="Content-Type: application/json" --body-data="$2" "$1"
fi
}

View File

@@ -0,0 +1,20 @@
#
put_save() { #推送面板选择
[ -z "$3" ] && request_type=PUT || request_type=$3
if curl --version >/dev/null 2>&1; then
curl -sS -X "$request_type" -H "Authorization: Bearer $secret" -H "Content-Type:application/json" "$1" -d "$2" >/dev/null
elif wget --version >/dev/null 2>&1; then
wget -q --method="$request_type" --header="Authorization: Bearer $secret" --header="Content-Type:application/json" --body-data="$2" "$1" >/dev/null
fi
}
web_restore() { #还原面板选择
num=$(cat "$CRASHDIR"/configs/web_save | wc -l)
i=1
while [ "$i" -le "$num" ]; do
group_name=$(awk -F ',' 'NR=="'${i}'" {print $1}' "$CRASHDIR"/configs/web_save | sed 's/ /%20/g')
now_name=$(awk -F ',' 'NR=="'${i}'" {print $2}' "$CRASHDIR"/configs/web_save)
put_save "http://127.0.0.1:${db_port}/proxies/${group_name}" "{\"name\":\"${now_name}\"}"
i=$((i + 1))
done
}

32
scripts/libs/web_save.sh Normal file
View File

@@ -0,0 +1,32 @@
#
get_save() { #获取面板信息
if curl --version >/dev/null 2>&1; then
curl -s -H "Authorization: Bearer ${secret}" -H "Content-Type:application/json" "$1"
elif [ -n "$(wget --help 2>&1 | grep '\-\-method')" ]; then
wget -q --header="Authorization: Bearer ${secret}" --header="Content-Type:application/json" -O - "$1"
fi
}
web_save() { #最小化保存面板节点选择
#使用get_save获取面板节点设置
get_save "http://127.0.0.1:${db_port}/proxies" | sed 's/{}//g' | sed 's/:{/\
/g'| grep -aE '"Selector"' >"$TMPDIR"/web_proxies
[ -s "$TMPDIR"/web_proxies ] && while read line; do
def=$(echo $line | grep -oE '"all".*",' | awk -F "[\"]" '{print $4}')
now=$(echo $line | grep -oE '"now".*",' | awk -F "[\"]" '{print $4}')
[ "$def" != "$now" ] && {
name=$(echo $line | grep -oE '"name".*",' | awk -F "[\"]" '{print $4}')
echo "${name},${now}" >>"$TMPDIR"/web_save
}
done <"$TMPDIR"/web_proxies
rm -rf "$TMPDIR"/web_proxies
#对比文件,如果有变动则写入磁盘,否则清除缓存
for file in web_save; do
if [ -s "$TMPDIR/$file" ]; then
. "$CRASHDIR"/libs/compare.sh && compare "$TMPDIR/$file" "$CRASHDIR/configs/$file"
[ "$?" = 0 ] && rm -f "$TMPDIR/$file" || mv -f "$TMPDIR/$file" "$CRASHDIR/configs/$file"
else
> "$CRASHDIR/configs/$file" #空文件时移除旧文件
fi
done
}

File diff suppressed because it is too large Load Diff

80
scripts/menus/1_start.sh Normal file
View File

@@ -0,0 +1,80 @@
#!/bin/sh
# Copyright (C) Juewuy
[ -n "$__IS_MODULE_1_START_LOADED" ] && return
__IS_MODULE_1_START_LOADED=1
load_lang 1_start
# ===== 启动完成提示 =====
startover() {
line_break
separator_line "="
content_line "\033[32m$START_SERVICE_OK\033[0m"
content_line "$START_WEB_HINT \033[4;36mhttp://$host$hostdir\033[0m $START_WEB_HINT2"
if [ "$firewall_area" = 4 ]; then
content_line ""
content_line "$START_PAC_HINT \033[4;32mhttp://$host:$db_port/ui/pac\033[0m"
content_line "$START_PROXY_HINT IP{\033[36m$host\033[0m} Port{\033[36m$mix_port\033[0m}"
fi
separator_line "="
line_break
sleep 1
return 0
}
# ===== 启动核心 =====
start_core() {
if echo "$crashcore" | grep -q 'singbox'; then
core_config="$CRASHDIR/jsons/config.json"
else
core_config="$CRASHDIR/yamls/config.yaml"
fi
if [ ! -s "$core_config" ] && [ -s "$CRASHDIR/configs/providers.cfg" ]; then
if [ "$crashcore" = singboxr ];then
CORE_TYPE=singbox
else
CORE_TYPE=clash
fi
. "$CRASHDIR/menus/providers_$CORE_TYPE.sh" && gen_providers
line_break
separator_line "="
content_line "\033[33m$START_NO_CORE_CFG_TRY_GEN\033[0m"
separator_line "="
elif [ -s "$core_config" ] || [ -n "$Url" ] || [ -n "$Https" ]; then
"$CRASHDIR/start.sh" start
# 循环检测服务启动状态
. "$CRASHDIR/libs/start_wait.sh"
[ -n "$test" ] || pidof CrashCore >/dev/null && {
# 启动 TG 机器人
if [ "$bot_tg_service" = ON ]; then
. "$CRASHDIR/menus/bot_tg_service.sh" && bot_tg_start
fi
startover
}
else
line_break
separator_line "="
content_line "\033[31m$START_NO_CORE_CFG_IMPORT_FIRST\033[0m"
separator_line "="
. "$CRASHDIR/menus/6_core_config.sh" && set_core_config
fi
}
# ===== 启动服务入口 =====
start_service() {
if [ "$firewall_area" = 5 ]; then
"$CRASHDIR/start.sh" start
line_break
separator_line "="
content_line "\033[32m$START_FIREWALL_DONE\033[0m"
separator_line "="
line_break
else
start_core
fi
}

823
scripts/menus/2_settings.sh Normal file
View File

@@ -0,0 +1,823 @@
#!/bin/sh
# Copyright (C) Juewuy
[ -n "$__IS_MODULE_2_SETTINGS_LOADED" ] && return
__IS_MODULE_2_SETTINGS_LOADED=1
load_lang 2_settings
# 功能设置
settings() {
while true; do
# 获取设置默认显示
[ -z "$skip_cert" ] && skip_cert=ON
[ -z "$sniffer" ] && sniffer=OFF
[ -z "$dns_mod" ] && dns_mod='redir_host'
line_break
separator_line "="
content_line "\033[30;47m$SET_MENU_TITLE\033[0m"
separator_line "="
content_line "1) $SET_MENU_REDIR\t\033[36m$redir_mod$MENU_MOD\033[0m"
content_line "2) $SET_MENU_DNS\t\033[36m$dns_mod\033[0m"
content_line "3) $SET_MENU_FW_FILTER"
[ "$disoverride" != "1" ] && {
content_line "4) $SET_MENU_SKIP_CERT\t\033[36m$skip_cert\033[0m"
content_line "5) $SET_MENU_SNIFFER\t\033[36m$sniffer\033[0m"
content_line "6) $SET_MENU_ADV_PORT"
}
content_line "8) $SET_MENU_IPV6\t\033[36m$ipv6_redir\033[0m"
separator_line "-"
content_line "a) \033[31m$SET_MENU_RESET\033[0m"
content_line "b) \033[36m$SET_MENU_LANG\033[0m"
content_line "c) \033[33m$SET_MENU_UI\033[0m"
content_line "0) $COMMON_BACK"
separator_line "="
read -r -p "$COMMON_INPUT> " num
case "$num" in
"" | 0)
break
;;
1)
if [ "$USER" != root ] && [ "$USER" != admin ]; then
line_break
separator_line "="
content_line "$SET_WARN_NONROOT"
separator_line "="
content_line "1) 是"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "$COMMON_INPUT> " res
if [ "$res" = 1 ]; then
set_redir_mod
else
continue
fi
else
set_redir_mod
fi
;;
2)
. "$CRASHDIR"/menus/dns.sh && set_dns_mod
;;
3)
. "$CRASHDIR"/menus/fw_filter.sh && set_fw_filter
;;
4)
line_break
separator_line "="
if [ "$skip_cert" = "OFF" ]; then
content_line "当前\033[33m已禁用\033[0m跳过本地证书验证是否确认启用"
else
content_line "当前\033[33m已启用\033[0m跳过本地证书验证是否确认禁用"
fi
separator_line "="
content_line "1) 是"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "$COMMON_INPUT> " num
if [ "$num" = 1 ]; then
line_break
separator_line "="
if [ "$skip_cert" = OFF ]; then
skip_cert=ON
content_line "\033[33m$SET_SKIP_CERT_ON\033[0m"
else
skip_cert=OFF
content_line "\033[33m$SET_SKIP_CERT_OFF\033[0m"
fi
setconfig skip_cert $skip_cert
separator_line "="
else
continue
fi
sleep 1
;;
5)
line_break
separator_line "="
if [ "$sniffer" = "OFF" ]; then
content_line "当前\033[33m已禁用\033[0m域名嗅探是否确认启用"
separator_line "="
content_line "1) 是"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "$COMMON_INPUT> " num
if [ "$num" = 1 ]; then
line_break
separator_line "="
if [ "$crashcore" = "clash" ]; then
rm -rf "$TMPDIR/CrashCore" "$CRASHDIR/CrashCore" "$CRASHDIR/CrashCore.tar.gz"
crashcore=meta
setconfig crashcore $crashcore
line_break
content_line "$SET_SNIFFER_CORE_SWITCH"
content_line ""
fi
sniffer=ON
else
continue
fi
elif [ "$crashcore" = clashpre ] && [ "$dns_mod" = redir_host ]; then
content_line "\033[31m$SET_SNIFFER_LOCKED\033[0m"
separator_line "="
sleep 1
continue
else
content_line "当前\033[33m已启用\033[0m域名嗅探是否确认禁用"
separator_line "="
content_line "1) 是"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "$COMMON_INPUT> " num
if [ "$num" = 1 ]; then
sniffer=OFF
line_break
separator_line "="
else
continue
fi
fi
setconfig sniffer "$sniffer"
content_line "\033[32m操作成功\033[0m"
separator_line "="
sleep 1
;;
6)
if pidof CrashCore >/dev/null; then
line_break
separator_line "="
content_line "\033[33m$SET_CORE_RUNNING\033[0m"
content_line "$SET_CORE_STOP_CONFIRM"
separator_line "="
content_line "1) 是"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "$COMMON_INPUT> " res
if [ "$res" = 1 ]; then
"$CRASHDIR/start.sh" stop && set_adv_config
else
continue
fi
else
set_adv_config
fi
;;
8)
set_ipv6
;;
a)
BACK_TAR="$CRASHDIR/configs.tar.gz"
line_break
separator_line "="
content_line "1) $SET_BACKUP"
content_line "2) $SET_RESTORE"
content_line "3) $SET_RESET"
content_line "0) $COMMON_BACK"
separator_line "="
read -r -p "$COMMON_INPUT> " num
case "$num" in
"" | 0)
continue
;;
1)
line_break
separator_line "="
if tar -zcf "$BACK_TAR" -C "$CRASHDIR/configs/" .; then
content_line "\033[32m$SET_BACKUP_OK $BACK_TAR\033[0m"
else
content_line "\033[31m$SET_BACKUP_FAIL\033[0m"
fi
sleep 1
continue
;;
2)
line_break
separator_line "="
if [ -f "$BACK_TAR" ]; then
tar -zcf "$TMPDIR/configs.tar.gz" -C "$CRASHDIR/configs/" .
rm -rf "$CRASHDIR/configs/*"
tar -zxf "$BACK_TAR" -C "$CRASHDIR"/configs
mv -f "$TMPDIR/configs.tar.gz" "$BACK_TAR"
content_line "\033[32m$SET_RESTORE_OK $BACK_TAR\033[0m"
else
content_line "\033[31m$SET_BACKUP_MISS\033[0m"
fi
;;
3)
line_break
separator_line "="
if tar -zcf "$BACK_TAR" -C "$CRASHDIR/configs/" .; then
rm -rf "$CRASHDIR/configs"
. "$CRASHDIR/init.sh" >/dev/null
content_lin e"\033[32m$SET_RESET_OK\033[0m"
else
content_lin e"\033[32m$SET_RESET_FAIL\033[0m"
fi
;;
*)
errornub
sleep 1
continue
;;
esac
content_line "\033[33m$SET_NEED_RESTART\033[0m"
sleep 1
exit 0
;;
b)
line_break
separator_line "="
content_line "1) 简体中文"
content_line "2) English"
content_line "0) $COMMON_BACK"
separator_line "="
read -r -p "$COMMON_INPUT> " num
case "$num" in
"" | 0)
continue
;;
1)
line_break
separator_line "="
echo chs >"$CRASHDIR"/configs/i18n.cfg
content_line "\033[32m切换成功请重新运行脚本\033[0m"
;;
2)
line_break
separator_line "="
echo en >"$CRASHDIR"/configs/i18n.cfg
content_line "\033[32mLanguage switched successfully! Please re-run the script!\033[0m"
;;
esac
separator_line "="
line_break
sleep 1
exit 0
;;
c)
line_break
separator_line "="
content_line "1) New Design by Sofia-Riese"
content_line "2) TUI-lite"
content_line "0) $COMMON_BACK"
separator_line "="
read -r -p "$COMMON_INPUT> " num
case "$num" in
"" | 0)
continue
;;
1)
setconfig tui_type 'tui_layout'
. "$CRASHDIR"/menus/tui_layout.sh
;;
2)
setconfig tui_type 'tui_lite'
. "$CRASHDIR"/menus/tui_lite.sh
;;
esac
line_break
separator_line "="
content_line "\033[32m切换成功\033[0m"
separator_line "="
sleep 1
;;
*)
errornum
sleep 1
;;
esac
done
}
set_redir_config() {
setconfig redir_mod "$redir_mod"
setconfig dns_mod "$dns_mod"
line_break
separator_line "="
content_line "\033[36m$SET_REDIR_APPLIED $redir_mod\033[0m"
separator_line "="
sleep 1
}
# 路由模式设置
set_redir_mod() {
while true; do
[ -n "$(ls /dev/net/tun 2>/dev/null)" ] || ip tuntap >/dev/null 2>&1 || modprobe tun 2>/dev/null && sup_tun=1
[ -z "$firewall_area" ] && firewall_area=1
[ "$firewall_area" = 4 ] && redir_mod="$MENU_PURE_MOD"
[ -z "$redir_mod" ] && redir_mod='Redir'
firewall_area_dsc=$(echo "$SET_FW_AREA_DESC($bypass_host)" | cut -d'|' -f$firewall_area)
line_break
separator_line "="
content_line "\033[33m$SET_REDIR_RESTART_HINT\033[0m"
content_line "$SET_REDIR_CURRENT\033[47;30m$redir_mod$MENU_MOD\033[0m $SET_CORE_CURRENT\033[47;30m$crashcore\033[0m"
separator_line "="
[ "$firewall_area" -le 3 ] && {
content_line "1) \033[32m$SET_REDIR_REDIR\033[0m\t$SET_REDIR_REDIRDES"
content_line "2) \033[36m$SET_REDIR_MIX\033[0m\t$SET_REDIR_MIXDES"
content_line "3) \033[32m$SET_REDIR_TPROXY\033[0m$SET_REDIR_TPROXYDES"
content_line "4) \033[33m$SET_REDIR_TUN\033[0m\t$SET_REDIR_TUNDES"
content_line ""
}
[ "$firewall_area" = 5 ] && {
content_line "5) \033[32mTCP旁路转发\033[0m 仅转发TCP流量至旁路由"
content_line "6) \033[36mT&U旁路转发\033[0m 转发TCP&UDP流量至旁路由"
content_line ""
}
content_line "7) $SET_FW_AREA\t\033[47;30m$firewall_area_dsc\033[0m"
content_line "8) $SET_VM_REDIR\t\033[47;30m$vm_redir\033[0m"
content_line "9) $SET_FW_SWITCH\t\033[47;30m$firewall_mod\033[0m"
content_line ""
content_line "0 $COMMON_BACK"
separator_line "="
read -r -p "$COMMON_INPUT> " num
case "$num" in
"" | 0)
break
;;
1)
redir_mod=Redir
set_redir_config
;;
2)
if [ -n "$sup_tun" ]; then
redir_mod=Mix
set_redir_config
else
line_break
separator_line "="
content_line "\033[31m${SET_NO_MOD}TUN\033[0m"
content_line "\033[31m$SET_NO_MOD2\033[0m"
separator_line "="
sleep 1
fi
;;
3)
if [ "$firewall_mod" = "iptables" ]; then
if [ -f /etc/init.d/qca-nss-ecm ] && [ "$systype" = "mi_snapshot" ]; then
read -r -p "$XIAOMI_QOS(1/0)> " res
[ "$res" = '1' ] && {
/data/shellcrash_init.sh tproxyfix
redir_mod=Tproxy
set_redir_config
}
elif grep -qE '^TPROXY$' /proc/net/ip_tables_targets || modprobe xt_TPROXY >/dev/null 2>&1; then
redir_mod=Tproxy
set_redir_config
else
line_break
separator_line "="
content_line "\033[31m${SET_NO_MOD}iptables-mod-tproxy\033[0m"
content_line "\033[31m$SET_NO_MOD2\033[0m"
separator_line "="
sleep 1
fi
elif [ "$firewall_mod" = "nftables" ]; then
if modprobe nft_tproxy >/dev/null 2>&1 || lsmod 2>/dev/null | grep -q nft_tproxy; then
redir_mod=Tproxy
set_redir_config
else
line_break
separator_line "="
content_line "\033[31m${SET_NO_MOD}nft_tproxy\033[0m"
content_line "\033[31m$SET_NO_MOD2\033[0m"
separator_line "="
sleep 1
fi
fi
;;
4)
if [ -n "$sup_tun" ]; then
redir_mod=Tun
set_redir_config
else
line_break
separator_line "="
content_line "\033[31m$SET_NO_TUN\033[0m"
separator_line "="
sleep 1
fi
;;
5)
redir_mod='TCP旁路转发'
set_redir_config
;;
6)
redir_mod='T&U旁路转发'
set_redir_config
;;
7)
set_firewall_area
;;
8)
set_firewall_vm
;;
9)
if [ "$firewall_mod" = 'iptables' ]; then
if nft add table inet shellcrash 2>/dev/null; then
firewall_mod=nftables
redir_mod=Redir
setconfig redir_mod $redir_mod
else
line_break
separator_line "="
content_line "\033[31m$FW_NO_NFTABLES\033[0m"
separator_line "="
fi
elif [ "$firewall_mod" = 'nftables' ]; then
if ckcmd iptables; then
firewall_mod=iptables
redir_mod=Redir
setconfig redir_mod $redir_mod
else
line_break
separator_line "="
content_line "\033[31m$FW_NO_IPTABLES\033[0m"
separator_line "="
fi
else
iptables -j REDIRECT -h >/dev/null 2>&1 && firewall_mod=iptables
nft add table inet shellcrash 2>/dev/null && firewall_mod=nftables
if [ -n "$firewall_mod" ]; then
redir_mod=Redir
setconfig redir_mod $redir_mod
setconfig firewall_mod "$firewall_mod"
else
line_break
separator_line "="
content_line "\033[31m$FW_NO_FIREWALL_BACKEND\033[0m"
separator_line "="
fi
fi
sleep 1
setconfig firewall_mod "$firewall_mod"
;;
*)
errornum
sleep 1
;;
esac
done
}
inputport() {
line_break
read -r -p "$INPUT_PORT165535> " portx
. "$CRASHDIR"/menus/check_port.sh # 加载测试函数
line_break
separator_line "="
if check_port "$portx"; then
setconfig "$xport" "$portx"
content_line "\033[32m$COMMON_SUCCESS\033[0m"
separator_line "="
sleep 1
return 0
else
content_line "\033[31m$COMMON_FAILED\033[0m"
separator_line "="
sleep 1
return 1
fi
}
# 端口设置
set_adv_config() {
while true; do
. "$CFG_PATH" >/dev/null
[ -z "$secret" ] && secret="$COMMON_UNSET"
[ -z "$table" ] && table=100
[ -z "$authentication" ] && auth="$COMMON_UNSET" || auth="******"
line_break
separator_line "="
content_line "1) $ADV_HTTP_PORT\t\033[36m$mix_port\033[0m"
content_line "2) $ADV_HTTP_AUTH\t\033[36m$auth\033[0m"
content_line "3) $ADV_REDIR_PORT\t\033[36m$redir_port,$((redir_port + 1))\033[0m"
content_line "4) $ADV_DNS_PORT\t\t\033[36m$dns_port\033[0m"
content_line "5) $ADV_PANEL_PORT\t\t\033[36m$db_port\033[0m"
content_line "6) $ADV_PANEL_PASS\t\t\033[36m$secret\033[0m"
content_line "8) $ADV_HOST\t\033[36m$host\033[0m"
content_line "9) $ADV_TABLE\t\t\033[36m$table,$((table + 1))\033[0m"
content_line "0) $COMMON_BACK"
separator_line "="
read -r -p "$COMMON_INPUT> " num
case "$num" in
"" | 0)
break
;;
1)
xport=mix_port
inputport
if [ $? -eq 1 ]; then
break
else
continue
fi
;;
2)
line_break
separator_line "="
content_line "$ADV_AUTH_FORMAT_DESC"
content_line "$ADV_AUTH_WARN"
content_line "$ADV_AUTH_REMOVE_HINT"
separator_line "="
read -r -p "$ADV_AUTH_INPUT> " input
line_break
separator_line "="
if [ "$input" = "0" ]; then
authentication=""
setconfig authentication
content_line "\033[32m$ADV_AUTH_REMOVED\033[0m"
else
if [ "$local_proxy" = "ON" ] && [ "$local_type" = "$LOCAL_TYPE_ENV" ]; then
content_line "\033[33m$ADV_AUTH_ENV_CONFLICT\033[0m"
else
authentication=$(echo "$input" | grep :)
if [ -n "$authentication" ]; then
setconfig authentication "'$authentication'"
content_line "\033[32m$COMMON_SUCCESS\033[0m"
else
content_line "\033[31m$ADV_AUTH_INVALID\033[0m"
fi
fi
fi
separator_line "="
sleep 1
;;
3)
xport=redir_port
inputport
if [ $? -eq 1 ]; then
break
else
continue
fi
;;
4)
xport=dns_port
inputport
if [ $? -eq 1 ]; then
break
else
continue
fi
;;
5)
xport=db_port
inputport
if [ $? -eq 1 ]; then
break
else
continue
fi
;;
6)
line_break
read -r -p "$ADV_PANEL_PASS_INPUT> " secret
if [ -n "$secret" ]; then
[ "$secret" = "0" ] && secret=""
setconfig secret "$secret"
line_break
separator_line "="
content_line "\033[32m$COMMON_SUCCESS\033[0m"
separator_line "="
fi
;;
8)
line_break
separator_line "="
content_line "\033[33m$ADV_HOST_WARN_LAN\033[0m"
content_line "\033[31m$ADV_HOST_WARN_CHANGE\033[0m"
separator_line "="
read -r -p "$ADV_HOST_INPUT> " host
line_break
separator_line "="
if [ "$host" = "0" ]; then
host=""
setconfig host "$host"
content_line "\033[32m$ADV_HOST_REMOVED\033[0m"
separator_line "="
sleep 1
exit 0
elif echo "$host" | grep -Eq '\<([1-9]|[1-9][0-9]|1[0-9]{2}|2[01][0-9]|22[0-3])\>(\.\<([0-9]|[0-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\>){2}\.\<([1-9]|[0-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-4])\>'; then
setconfig host "$host"
content_line "\033[32m$COMMON_SUCCESS\033[0m"
else
host=""
content_line "\033[31m$ADV_HOST_INVALID\033[0m"
fi
separator_line "="
sleep 1
;;
9)
line_break
separator_line "="
content_line "\033[33m$ADV_TABLE_WARN\033[0m"
separator_line "="
read -r -p "$ADV_TABLE_INPUT> " table
if [ -n "$table" ]; then
[ "$table" = "0" ] && table="100"
setconfig table "$table"
line_break
separator_line "="
content_line "\033[32m$COMMON_SUCCESS\033[0m"
separator_line "="
fi
;;
*)
errornum
sleep 1
;;
esac
done
}
set_firewall_area() {
while true; do
[ -z "$vm_redir" ] && vm_redir='OFF'
line_break
separator_line "="
content_line "\033[33m$FW_AREA_NOTE_1\033[0m"
content_line "\033[33m$FW_AREA_NOTE_2\033[0m"
content_line ""
content_line "当前路由劫持范围:$firewall_area_dsc"
separator_line "="
content_line "1) \033[32m$FW_AREA_LAN\033[0m"
content_line "2) \033[36m$FW_AREA_LOCAL\033[0m"
content_line "3) \033[32m$FW_AREA_BOTH\033[0m"
content_line "4) $FW_AREA_NONE"
content_line "0) $COMMON_BACK"
separator_line "="
read -r -p "$COMMON_INPUT> " num
case "$num" in
"" | 0)
break
;;
[1-4])
if [ "$firewall_area" -ge 4 ]; then
redir_mod=''
else
redir_mod=Redir
fi
firewall_area="$num"
setconfig firewall_area "$firewall_area"
setconfig redir_mod "$redir_mod"
case "$firewall_area" in
1) firewall_area_dsc="$FW_AREA_LAN" ;;
2) firewall_area_dsc="$FW_AREA_LOCAL" ;;
3) firewall_area_dsc="$FW_AREA_BOTH" ;;
4) firewall_area_dsc="$FW_AREA_NONE" ;;
esac
line_break
separator_line "="
content_line "\033[32m操作成功\033[0m"
separator_line "="
sleep 1
;;
5)
line_break
separator_line "="
content_line "\033[31m注意\033[0m"
content_line "此功能存在多种风险如无网络基础请勿尝试!"
content_line "如需代理UDP请确保旁路由运行了支持UDP代理的模式"
content_line "如使用systemd方式启动内核依然会空载运行建议使用保守模式"
content_line "\033[33m说明\033[0m"
content_line "此功能不启动内核仅配置防火墙转发且子设备无需额外设置网关DNS"
content_line "支持防火墙分流及设备过滤支持部分定时任务但不支持ipv6"
separator_line "="
read -r -p "请直接输入旁路由IPV4地址> " bypass_host
[ -n "$bypass_host" ] && {
firewall_area=$num
setconfig firewall_area "$firewall_area"
setconfig bypass_host "$bypass_host"
redir_mod=TCP旁路转发
setconfig redir_mod $redir_mod
}
;;
*)
errornum
sleep 1
;;
esac
done
}
set_firewall_vm() {
[ -z "$vm_ipv4" ] && vm_ipv4=$(ip a 2>&1 | grep -w 'inet' | grep 'global' | grep 'brd' | grep -E 'docker|podman|virbr|vnet|ovs|vmbr|veth|vmnic|vboxnet|lxcbr|xenbr|vEthernet' | sed 's/.*inet.//g' | sed 's/ br.*$//g' | sed 's/metric.*$//g' | tr '\n' ' ')
line_break
separator_line "="
content_line "$VM_DETECT_DESC\033[32m$vm_ipv4\033[0m"
separator_line "="
content_line "1) \033[32m$VM_ENABLE_AUTO\033[0m"
content_line "2) \033[36m$VM_ENABLE_MANUAL\033[0m"
content_line "3) \033[31m$VM_DISABLE\033[0m"
content_line "0) $COMMON_BACK"
separator_line "="
read -r -p "$COMMON_INPUT> " num
case "$num" in
1)
line_break
separator_line "="
if [ -n "$vm_ipv4" ]; then
vm_redir=ON
content_line "\033[32m操作成功\033[0m"
else
content_line "\033[33m$VM_NO_NET_DETECTED\033[0m"
fi
separator_line "="
sleep 1
;;
2)
line_break
separator_line "="
content_line "$VM_INPUT_DESC_1"
content_line "$VM_INPUT_DESC_2 \033[32m10.88.0.0/16 172.17.0.0/16\033[0m"
content_line ""
content_line "Tips直接回车确认可返回上级菜单"
separator_line "="
read -r -p "$VM_INPUT_NET> " text
[ -n "$text" ] && vm_ipv4="$text" && vm_redir=ON
;;
3)
vm_redir=OFF
vm_ipv4=''
line_break
separator_line "="
content_line "\033[32m操作成功\033[0m"
separator_line "="
sleep 1
;;
*) ;;
esac
case "$num" in
1-3)
setconfig vm_redir "$vm_redir"
setconfig vm_ipv4 "'$vm_ipv4'"
;;
esac
}
# ipv6设置
set_ipv6() {
while true; do
[ -z "$ipv6_redir" ] && ipv6_redir=OFF
[ -z "$ipv6_dns" ] && ipv6_dns=ON
line_break
separator_line "="
content_line "1) $IPV6_REDIR\t\033[36m$ipv6_redir\033[0m"
[ "$disoverride" != "1" ] && content_line "2) $IPV6_DNS\t\033[36m$ipv6_dns\033[0m"
content_line "0) $COMMON_BACK"
separator_line "="
read -r -p "$COMMON_INPUT> " num
case "$num" in
"" | 0)
break
;;
1)
if [ "$ipv6_redir" = "OFF" ]; then
ipv6_support=ON
ipv6_redir=ON
else
ipv6_redir=OFF
fi
setconfig ipv6_redir $ipv6_redir
setconfig ipv6_support "$ipv6_support"
line_break
separator_line "="
content_line "\033[32m操作成功\033[0m"
separator_line "="
sleep 1
;;
2)
[ "$ipv6_dns" = OFF ] && ipv6_dns=ON || ipv6_dns=OFF
setconfig ipv6_dns "$ipv6_dns"
line_break
separator_line "="
content_line "\033[32m操作成功\033[0m"
separator_line "="
sleep 1
;;
*)
errornum
sleep 1
;;
esac
done
}

290
scripts/menus/4_setboot.sh Normal file
View File

@@ -0,0 +1,290 @@
#!/bin/sh
# Copyright (C) Juewuy
[ -n "$__IS_MODULE_4_SETBOOT_LOADED" ] && return
__IS_MODULE_4_SETBOOT_LOADED=1
allow_autostart() {
if [ -f /etc/rc.common ] && [ "$(cat /proc/1/comm)" = "procd" ]; then
/etc/init.d/shellcrash enable
fi
ckcmd systemctl && systemctl enable shellcrash.service >/dev/null 2>&1
grep -q 's6' /proc/1/comm && touch /etc/s6-overlay/s6-rc.d/user/contents.d/afstart
rc-status -r >/dev/null 2>&1 && rc-update add shellcrash default >/dev/null 2>&1
rm -rf "$CRASHDIR"/.dis_startup
}
disable_autostart() {
[ -d /etc/rc.d ] && cd /etc/rc.d && rm -rf *shellcrash >/dev/null 2>&1 && cd - >/dev/null
ckcmd systemctl && systemctl disable shellcrash.service >/dev/null 2>&1
grep -q 's6' /proc/1/comm && rm -rf /etc/s6-overlay/s6-rc.d/user/contents.d/afstart
rc-status -r >/dev/null 2>&1 && rc-update del shellcrash default >/dev/null 2>&1
touch "$CRASHDIR"/.dis_startup
}
# 启动设置菜单
setboot() {
while true; do
[ -z "$start_old" ] && start_old=OFF
if [ -z "$start_delay" ] || [ "$start_delay" = 0 ]; then
delay=未设置
else
delay="${start_delay}"
fi
check_autostart && auto_set="ON" || auto_set="OFF"
[ "${BINDIR}" = "$CRASHDIR" ] && mini_clash=OFF || mini_clash=ON
[ -z "$network_check" ] && network_check=ON
line_break
separator_line "="
content_line "\033[30;47m启动设置菜单\033[0m"
separator_line "="
content_line "1) 开机自启动: \033[36m$(printf '%-4s' "$auto_set")\033[0m"
content_line "2) 使用保守模式: \033[36m$(printf '%-4s' "$start_old")\033[0m ———基于定时任务(每分钟检测)"
content_line "3) 设置自启延时: \033[36m$(printf '%-7s' "$delay")\033[0m ———用于解决自启后服务受限"
content_line "4) 启用小闪存模式: \033[36m$(printf '%-4s' "$mini_clash")\033[0m ———用于闪存空间不足的设备"
[ "${BINDIR}" != "$CRASHDIR" ] && content_line "5) 设置小闪存目录: \033[36m${BINDIR}\033[0m"
content_line "6) 自启网络检查: \033[36m$(printf '%-4s' "$network_check")\033[0m ———禁用则跳过自启时网络检查"
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " num
case "$num" in
"" | 0)
break
;;
1)
line_break
separator_line "="
if check_autostart; then
# 禁止自启动:删除各系统的启动项
disable_autostart
content_line "\033[33m已禁止ShellCrash开机自启动\033[0m"
else
# 允许自启动:配置各系统的启动项
allow_autostart
content_line "\033[32m已设置ShellCrash开机自启动\033[0m"
fi
separator_line "="
;;
2)
line_break
separator_line "="
if [ "$start_old" = "OFF" ] >/dev/null 2>&1; then
disable_autostart
start_old=ON
setconfig start_old "$start_old"
"$CRASHDIR"/start.sh stop
content_line "\033[33m改为使用保守模式启动服务\033[0m"
else
if grep -qE 'procd|systemd|s6' /proc/1/comm || rc-status -r >/dev/null 2>&1; then
"$CRASHDIR"/start.sh cronset "ShellCrash初始化"
start_old=OFF
setconfig start_old "$start_old"
"$CRASHDIR"/start.sh stop
content_line "\033[32m改为使用系统守护进程启动服务\033[0m"
else
content_line "\033[31m当前设备不支持以其他模式启动\033[0m"
fi
fi
separator_line "="
sleep 1
;;
3)
line_break
separator_line "="
content_line "\033[33m如果你的设备启动后可以正常使用则无需设置\033[0m"
content_line "\033[36m推荐设置为30120秒之间请根据设备问题自行试验\033[0m"
separator_line "="
read -r -p "请输入启动延迟时间0300秒> " sec
line_break
separator_line "="
case "$sec" in
[0-9] | [0-9][0-9] | [0-2][0-9][0-9] | 300)
start_delay=$sec
setconfig start_delay "$sec"
content_line "\033[32m设置成功\033[0m"
;;
*)
content_line "\033[31m输入有误或超过300秒请重新输入\033[0m"
;;
esac
separator_line "="
sleep 1
;;
4)
dir_size=$(df "$CRASHDIR" | awk '{ for(i=1;i<=NF;i++){ if(NR==1){ arr[i]=$i; }else{ arr[i]=arr[i]" "$i; } } } END{ for(i=1;i<=NF;i++){ print arr[i]; } }' | grep Ava | awk '{print $2}')
line_break
separator_line "="
if [ "$mini_clash" = "OFF" ]; then
if [ "$dir_size" -gt 20480 ]; then
content_line "\033[33m您的设备空间充足>20M无需开启\033[0m"
elif [ "$start_old" != 'ON' ] && [ "$(cat /proc/1/comm)" = "systemd" ]; then
content_line "\033[33m不支持systemd启动模式请先启用保守模式\033[0m"
else
[ "$BINDIR" = "$CRASHDIR" ] && BINDIR="$TMPDIR"
content_line "\033[32m已经启用小闪存功能\033[0m"
content_line "如需更换目录,请使用【设置小闪存目录】功能\033[0m"
fi
separator_line "="
else
if [ "$dir_size" -lt 8192 ]; then
content_line "\033[31m您的设备剩余空间不足8M停用后可能无法正常运行\033[0m"
content_line "是否确认停用此功能:"
separator_line "="
content_line "1) 是"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " res
if [ "$res" = 1 ]; then
BINDIR="$CRASHDIR"
line_break
separator_line "="
content_line "\033[33m已经停用小闪存功能\033[0m"
separator_line "="
else
continue
fi
else
rm -rf /tmp/ShellCrash
BINDIR="$CRASHDIR"
content_line "\033[33m已经停用小闪存功能\033[0m"
separator_line "="
fi
fi
setconfig BINDIR "$BINDIR" "$CRASHDIR"/configs/command.env
sleep 1
;;
5)
while true; do
line_break
separator_line "="
content_line "\033[33m如设置到内存则每次开机后都自动重新下载相关文件\033[0m"
content_line "\033[33m请确保安装源可用裸连否则会导致启动失败\033[0m"
separator_line "="
content_line "1) 使用内存(/tmp"
content_line "2) 选择U盘目录"
content_line "3) 自定义目录"
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " num
case "$num" in
"" | 0)
break
;;
1)
BINDIR="$TMPDIR"
;;
2)
set_usb_dir() {
while true; do
line_break
separator_line "="
content_line "请选择安装目录:"
separator_line "="
du -hL /mnt |
awk '{print NR") "$2" (已占用的储存空间:"$1""}' |
while IFS= read -r line; do
content_line "$line"
done
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " num
BINDIR=$(du -hL /mnt | awk '{print $2}' | sed -n "$num"p)
if [ "$num" = 0 ]; then
return 1
elif [ -z "$BINDIR" ]; then
line_break
separator_line "="
content_line "\033[31m输入错误请重新设置\033[0m"
separator_line "="
else
return 0
fi
done
}
set_usb_dir
if [ $? -eq 1 ]; then
continue
fi
;;
3)
input_dir() {
while true; do
line_break
separator_line "="
content_line "请直接输入命令语句"
content_line "或输入 0 返回上级菜单"
separator_line "="
read -r -p "请输入> " BINDIR
if [ "$BINDIR" = 0 ]; then
return 1
elif [ ! -d "$BINDIR" ]; then
line_break
separator_line "="
content_line "\033[31m输入错误请重新设置\033[0m"
separator_line "="
continue
fi
return 0
done
}
input_dir
if [ $? -eq 1 ]; then
continue
fi
;;
*)
errornum
sleep 1
continue
;;
esac
setconfig BINDIR "$BINDIR" "$CRASHDIR"/configs/command.env
break
done
;;
6)
line_break
separator_line "="
content_line "\033[33m如果你的设备启动后可以正常使用则无需变更设置\033[0m"
content_line "\033[36m禁用时如果使用了小闪存模式或者rule-set等在线规则则可能会因无法联网而导致启动失败\033[0m"
content_line "\033[32m启用时会导致部分性能较差或者拨号较慢的设备可能会因查询超时导致启动失败\033[0m"
separator_line "="
if [ "$network_check" = "OFF" ]; then
content_line "当前\033[33m已禁用\033[0m自启网络检查是否确认启用"
else
content_line "当前\033[33m已启用\033[0m自启网络检查是否确认禁用"
fi
separator_line "-"
content_line "1) 是"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " res
if [ "$res" = '1' ]; then
if [ "$network_check" = "OFF" ]; then
network_check=ON
else
network_check=OFF
fi
setconfig network_check "$network_check"
line_break
separator_line "="
content_line "\033[32m操作成功\033[0m"
separator_line "="
sleep 1
fi
;;
*)
errornum
sleep 1
;;
esac
done
}

534
scripts/menus/5_task.sh Normal file
View File

@@ -0,0 +1,534 @@
#!/bin/sh
# Copyright (C) Juewuy
[ -n "$__IS_MODULE_5_TASK_LOADED" ] && return
__IS_MODULE_5_TASK_LOADED=1
# 通用工具
. "$CRASHDIR"/libs/set_config.sh
. "$CRASHDIR"/libs/set_cron.sh
# 任务工具
set_cron() {
[ -z "$week" ] && week=*
[ -z "$hour" ] && hour=*
[ -z "$min" ] && min=0
line_break
separator_line "="
content_line "\033[33m$cron_time\033[0m执行任务\033[36m$task_name\033[0m"
content_line ""
content_line "是否确认添加定时任务:"
separator_line "="
content_line "1) 是"
content_line "0) 否"
separator_line "="
read -r -p "请输入对应标号> " res
if [ "$res" = '1' ]; then
task_txt="$min $hour * * $week $CRASHDIR/task/task.sh $task_id $cron_time$task_name"
cronset "$cron_time$task_name" "$task_txt"
line_break
separator_line "="
content_line "任务【$cron_time$task_name】\033[32m已添加\033[0m"
separator_line "="
fi
unset week hour min
sleep 1
}
set_service() {
# 参数1代表要任务类型,参数2代表任务ID,参数3代表任务描述,参数4代表running任务cron时间
task_file="$CRASHDIR"/task/$1
[ -s "$task_file" ] && sed -i "/$3/d" "$task_file"
# 运行时每分钟执行的任务特殊处理
if [ "$1" = "running" ]; then
task_txt="$4 $CRASHDIR/task/task.sh $2 $3"
echo "$task_txt" >>"$task_file"
[ -n "$(pidof CrashCore)" ] && cronset "$3" "$task_txt"
else
echo "$CRASHDIR/task/task.sh $2 $3" >>"$task_file"
fi
content_line "任务【$3】\033[32m添加成功\033[0m"
sleep 1
}
# 任务界面
#
# 自定义命令添加
task_user_add() {
while true; do
line_break
separator_line "="
content_line "\033[33m命令可包含空格请确保命令可执行\033[0m"
content_line "\033[36m请勿附带执行条件执行条件请在命令添加完成后再返回设置\033[0m"
content_line "亦可手动编辑\033[32m${CRASHDIR}/task/task.user\033[0m以添加命令"
separator_line "-"
content_line "请直接输入命令语句"
content_line "或输入 0 返回上级菜单"
separator_line "="
read -r -p "请输入> " script
if [ "$script" = 0 ]; then
break
elif [ -n "$script" ]; then
task_command=$script
line_break
separator_line "="
content_line "请检查输入:\033[32m$task_command\033[0m"
separator_line "="
# 获取本任务ID
task_max_id=$(awk -F '#' '{print $1}' "$CRASHDIR"/task/task.user 2>/dev/null | sort -n | tail -n 1)
[ -z "$task_max_id" ] && task_max_id=200
task_id=$((task_max_id + 1))
read -r -p "请输入任务备注> " txt
[ -n "$txt" ] && task_name=$txt || task_name=自定义任务$task_id
echo "$task_id#$task_command#$task_name" >>"$CRASHDIR"/task/task.user
line_break
separator_line "="
content_line "\033[32m自定义任务已添加\033[0m"
separator_line "="
sleep 1
break
else
line_break
separator_line "="
content_line "\033[31m输入错误请重新输入\033[0m"
separator_line "="
sleep 1
fi
done
}
# 自定义命令删除
task_user_del() {
while true; do
line_break
separator_line "="
if grep -Evq '^#' "$CRASHDIR/task/task.user" 2>/dev/null; then
content_line "请输入对应ID移除对应自定义任务不会影响内置任务"
content_line "也可以手动编辑\033[32m${CRASHDIR}/task/task.user\033[0m"
separator_line "="
grep -Ev '^#' "$CRASHDIR/task/task.user" 2>/dev/null |
awk -F '#' '{print $1") "$3}' |
while IFS= read -r line; do
content_line "$line"
done
content_line ""
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " num
if [ "$num" = 0 ]; then
break
elif [ -n "$num" ]; then
sed -i "/^$num#/d" "$CRASHDIR"/task/task.user 2>/dev/null
line_break
separator_line "="
content_line "\033[32m操作成功\033[0m"
separator_line "="
sleep 1
else
line_break
separator_line "="
content_line "\033[31m输入错误请重新输入\033[0m"
separator_line "="
sleep 1
fi
else
content_line "\033[33m你暂未添加任何自定义任务\033[0m"
separator_line "="
sleep 1
break
fi
done
}
# 任务添加
task_add() {
while true; do
line_break
separator_line "="
content_line "\033[36m请选择需要添加的任务\033[0m"
separator_line "="
# 输出任务列表
# cat "$CRASHDIR"/task/task.list "$CRASHDIR"/task/task.user 2>/dev/null | grep -Ev '^(#|$)' | awk -F '#' '{print NR") "$3}'
grep -Ev '^(#|$)' "$CRASHDIR/task/task.list" "$CRASHDIR/task/task.user" 2>/dev/null |
awk -F '#' '{print NR") "$3}' |
while IFS= read -r line; do
content_line "$line"
done
content_line ""
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " num
case "$num" in
0)
break
;;
[1-9] | [1-9][0-9])
if [ "$num" -le "$(cat "$CRASHDIR"/task/task.list "$CRASHDIR"/task/task.user 2>/dev/null | wc -l)" ]; then
task_id=$(cat "$CRASHDIR"/task/task.list "$CRASHDIR"/task/task.user 2>/dev/null | grep -Ev '^(#|$)' | sed -n "$num p" | awk -F '#' '{print $1}')
task_name=$(cat "$CRASHDIR"/task/task.list "$CRASHDIR"/task/task.user 2>/dev/null | grep -Ev '^(#|$)' | sed -n "$num p" | awk -F '#' '{print $3}')
task_type
break
else
errornum
sleep 1
fi
;;
*)
errornum
sleep 1
;;
esac
done
}
# 任务删除
task_del() {
# 删除定时任务
croncmd -l >"$TMPDIR"/cron
sed -i "/$1/d" "$TMPDIR"/cron && croncmd "$TMPDIR"/cron
rm -f "$TMPDIR"/cron
# 删除条件任务
sed -i "/$1/d" "$CRASHDIR"/task/cron 2>/dev/null
sed -i "/$1/d" "$CRASHDIR"/task/bfstart 2>/dev/null
sed -i "/$1/d" "$CRASHDIR"/task/afstart 2>/dev/null
sed -i "/$1/d" "$CRASHDIR"/task/running 2>/dev/null
sed -i "/$1/d" "$CRASHDIR"/task/affirewall 2>/dev/null
}
# 任务条件选择菜单
task_type() {
line_break
separator_line "="
content_line "请选择任务\033[36m【$task_name】\033[0m执行条件"
separator_line "="
content_line "1) 定时任务\033[32m每周执行\033[0m"
content_line "2) 定时任务\033[32m每日执行\033[0m"
content_line "3) 定时任务\033[32m每小时执行\033[0m"
content_line "4) 定时任务\033[32m每分钟执行\033[0m"
content_line " - - - - - - - - -\033[31m注意\033[0m- - - - - - - - -"
content_line " 逻辑水平不及格的请勿使用下方触发条件!"
content_line " - - - - - - - - - - - - - - - - - - - -"
content_line "5) 服务\033[33m启动前执行\033[0m"
content_line "6) 服务\033[33m启动后执行\033[0m"
content_line "7) 服务\033[33m运行时每分钟执行\033[0m"
content_line "8) 防火墙服务\033[33m重启后执行\033[0m"
content_line ""
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " num
case "$num" in
0)
return 1
;;
1)
line_break
separator_line "="
content_line "输入 17 对应\033[33m每周的指定某天\033[0m运行7=周日)"
content_line "输入 140 代表\033[36m每周一、周四、周日\033[0m运行"
content_line "输入 15 代表\033[36m周一至周五\033[0m运行"
separator_line "="
read -r -p "在每周哪天执行?> " week
# week=`echo ${week/7/0}` # 把7换成0
read -r -p "想在该日的具体哪个小时执行023> " hour
cron_time="在每周$week的$hour点整"
# cron_time=`echo ${cron_time/周0/周日}` # 把0换成日
[ -n "$week" ] && [ -n "$hour" ] && set_cron
;;
2)
line_break
separator_line "="
content_line "输入 1715 代表\033[36m每到1715点\033[0m运行"
content_line "输入 618 代表\033[36m早6点至晚18点间每小时\033[0m运行"
separator_line "="
read -r -p "想在每日的具体哪个小时执行0~23> " hour
read -r -p "想在具体哪分钟执行059的整数> " min
cron_time="在每日的$hour点$min分"
[ -n "$min" ] && [ -n "$hour" ] && set_cron
;;
3)
line_break
read -r -p "想每隔多少小时执行一次123的整数> " num
hour="*/$num"
cron_time="每隔$num小时"
[ -n "$hour" ] && set_cron
;;
4)
line_break
read -r -p "想每隔多少分钟执行一次159的整数> " num
min="*/$num"
cron_time="每隔$num分钟"
[ -n "$min" ] && set_cron
;;
5)
set_service bfstart "$task_id" "服务启动前$task_name"
;;
6)
set_service afstart "$task_id" "服务启动后$task_name"
;;
7)
line_break
separator_line "="
content_line "输入10即每隔10分钟运行一次1440即每隔24小时运行一次"
content_line "大于60分钟的数值将按小时取整且按当前时区记时"
separator_line "="
read -r -p "想每隔多少分钟执行一次11440的整数> " num
if [ "$num" -lt 60 ]; then
min="$num"
cron_time="*/$min * * * *"
time_des="$min分钟"
else
hour="$((num / 60))"
cron_time="0 */$hour * * *"
time_des="$hour小时"
fi
[ -n "$cron_time" ] && set_service running "$task_id" "运行时每$time_des$task_name" "$cron_time"
;;
8)
line_break
separator_line "="
content_line "该功能会将相关启动代码注入到/etc/init.d/firewall中"
content_line "是否确认继续:"
separator_line "="
content_line "1) 是"
content_line "0) 否"
separator_line "="
read -r -p "请输入对应标号> " res
[ "$res" = 1 ] && set_service affirewall "$task_id" "防火墙重启后$task_name"
;;
*)
errornum
return 1
;;
esac
}
# 任务管理列表
task_manager() {
while true; do
line_break
separator_line "="
# 抽取并生成临时列表
croncmd -l >"$TMPDIR"/task_cronlist
cat "$TMPDIR"/task_cronlist "$CRASHDIR"/task/running 2>/dev/null | sort -u | grep -oE "task/task.sh .*" | awk -F ' ' '{print $2" "$3}' >"$TMPDIR"/task_list
cat "$CRASHDIR"/task/bfstart "$CRASHDIR"/task/afstart "$CRASHDIR"/task/affirewall 2>/dev/null | awk -F ' ' '{print $2" "$3}' >>"$TMPDIR"/task_list
cat "$TMPDIR"/task_cronlist 2>/dev/null | sort -u | grep -oE " #.*" | grep -v "守护" | awk -F '#' '{print "0 旧版任务-"$2}' >>"$TMPDIR"/task_list
sed -i '/^ *$/d' "$TMPDIR"/task_list
rm -rf "$TMPDIR"/task_cronlist
# 判断为空则返回
if [ ! -s "$TMPDIR"/task_list ]; then
content_line "\033[31m当前没有可供管理的任务\033[36m"
separator_line "="
sleep 1
break
else
content_line "\033[33m已添加的任务\033[0m"
separator_line "="
# cat "$TMPDIR"/task_list | awk '{print NR ") " $2}'
awk '{print NR ") " $2}' "$TMPDIR/task_list" |
while IFS= read -r line; do
content_line "$line"
done
separator_line "-"
content_line "a) 清空旧版任务"
content_line "d) 清空任务列表"
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " num
case "$num" in
"" | 0)
break
;;
a)
task_del "#"
line_break
separator_line "="
content_line "\033[31m旧版任务已清空\033[36m"
separator_line "="
sleep 1
;;
d)
task_del "task.sh"
line_break
separator_line "="
content_line "\033[31m全部任务已清空\033[36m"
separator_line "="
sleep 1
;;
[1-9] | [1-9][0-9])
task_txt=$(sed -n "$num p" "$TMPDIR"/task_list)
task_id=$(echo "$task_txt" | awk '{print $1}')
line_break
separator_line "="
if [ "$task_id" = 0 ]; then
content_line "旧版任务不支持管理,是否移除:"
separator_line "="
content_line "1) 是"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " res
if [ "$res" = 1 ]; then
cronname=$(echo "$task_txt" | awk -F '-' '{print $2}')
croncmd -l >"$TMPDIR"/conf && sed -i "/$cronname/d" "$TMPDIR"/conf && croncmd "$TMPDIR"/conf
sed -i "/$cronname/d" $clashdir/tools/cron 2>/dev/null
rm -f "$TMPDIR"/conf
break
fi
else
task_des=$(echo "$task_txt" | awk '{print $2}')
task_name=$(cat "$CRASHDIR"/task/task.list "$CRASHDIR"/task/task.user 2>/dev/null | grep "$task_id" | awk -F '#' '{print $3}')
content_line "当前任务为:\033[36m$task_des\033[0m"
separator_line "="
content_line "1) \033[33m修改\033[0m当前任务"
content_line "2) \033[31m删除\033[0m当前任务"
content_line "3) \033[32m立即执行\033[0m一次"
content_line "4) 查看\033[33m执行记录\033[0m"
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " num
case "$num" in
"" | 0)
continue
;;
1)
task_type && task_del "$task_des"
;;
2)
task_del "$task_des"
line_break
separator_line "="
content_line "\033[32m操作成功\033[0m"
separator_line "="
;;
3)
task_command=$(cat "$CRASHDIR"/task/task.list "$CRASHDIR"/task/task.user 2>/dev/null | grep "$task_id" | awk -F '#' '{print $2}')
eval "$task_command" && task_res='执行成功!' || task_res='执行失败!'
line_break
separator_line "="
content_line "\033[33m任务【$task_des$task_res\033[0m"
separator_line "="
sleep 1
;;
4)
line_break
if cat "$TMPDIR"/ShellCrash.log | grep -q "$task_name"; then
cat "$TMPDIR"/ShellCrash.log | grep "$task_name"
else
separator_line "="
content_line "\033[31m未找到相关执行记录\033[0m"
separator_line "="
fi
sleep 1
;;
*)
errornum
sleep 1
;;
esac
fi
;;
*)
errornum
sleep 1
;;
esac
fi
done
}
# 任务推荐
task_recom() {
line_break
separator_line "="
content_line "\033[36m是否启用以下推荐的自动任务配置\033[0m"
content_line "每隔10分钟自动保存面板配置"
content_line "服务启动后自动同步ntp时间"
content_line "在每日的3点0分重启服务"
separator_line "="
content_line "1) 是"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " res
[ "$res" = 1 ] && {
line_break
separator_line "="
set_service running "106" "运行时每10分钟自动保存面板配置" "*/10 * * * *"
set_service afstart "107" "服务启动后自动同步ntp时间"
cronset "在每日的3点0分重启服务" "0 3 * * * ${CRASHDIR}/task/task.sh 103 在每日的3点0分重启服务" &&
content_line "任务【在每日的3点0分重启服务】\033[32m添加成功\033[0m"
separator_line "="
}
}
# 任务菜单
task_menu() {
while true; do
# 检测并创建自定义任务文件
[ -f "$CRASHDIR"/task/task.user ] || echo '#任务ID(必须>200并顺序排列)#任务命令#任务说明(#号隔开,任务命令和说明中都不允许包含#号)' >"$CRASHDIR"/task/task.user
line_break
separator_line "="
content_line "\033[30;47m自动任务菜单\033[0m"
separator_line "="
content_line "1) 添加\033[32m自动任务\033[0m"
content_line "2) 管理\033[33m任务列表\033[0m"
content_line "3) 查看\033[36m任务日志\033[0m"
content_line "4) 配置\033[36m日志推送\033[0m"
content_line "5) 添加\033[33m自定义任务\033[0m"
content_line "6) 删除\033[33m自定义任务\033[0m"
content_line "7) 使用\033[32m推荐设置\033[0m"
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " num
case "$num" in
"" | 0)
break
;;
1)
task_add
;;
2)
task_manager
rm -rf "$TMPDIR"/task_list
;;
3)
line_break
if cat "$TMPDIR"/ShellCrash.log | grep -q '任务【'; then
cat "$TMPDIR"/ShellCrash.log | grep '任务【'
else
separator_line "="
content_line "\033[31m未找到任务相关执行日志\033[0m"
separator_line "="
sleep 1
fi
;;
4)
line_break
separator_line "="
content_line "\033[36m请在日志工具中配置相关推送通道及推送开关\033[0m"
separator_line "="
. "$CRASHDIR"/menus/8_tools.sh && log_pusher
;;
5)
task_user_add
;;
6)
task_user_del
;;
7)
task_recom
;;
*)
errornum
sleep 1
;;
esac
done
}

View File

@@ -0,0 +1,395 @@
#!/bin/sh
# Copyright (C) Juewuy
[ -n "$__IS_MODULE_6_CORECONFIG_LOADED" ] && return
__IS_MODULE_6_CORECONFIG_LOADED=1
if echo "$crashcore" | grep -q 'singbox'; then
CONFIG_PATH="$CRASHDIR"/jsons/config.json
CORE_TYPE=singbox
else
CONFIG_PATH="$CRASHDIR"/yamls/config.yaml
CORE_TYPE=clash
fi
URI_EXP='ss|vmess|vless|trojan|tuic|anytls|shadowtls|hysteria(2)?'
# 配置文件主界面
set_core_config() {
while true; do
list=$(cat "$CRASHDIR"/configs/providers.cfg "$CRASHDIR"/configs/providers_uri.cfg 2>/dev/null |
awk '{
f1 = $1
f2 = $2
if (length(f1) > 12)
f1 = substr(f1, 1, 9) ".."
if (length(f2) > 39)
f2 = substr(f2, 1, 36) "..."
printf "%-10s\t%-30s\n", f1, f2
}')
comp_box "\033[30;47m配置文件管理\033[0m"
[ -n "$list" ] && {
content_line "\033[36m输入数字可管理对应提供者\033[0m"
list_box "$list"
separator_line "-"
}
content_line "a) \033[32m添加提供者\033[0m(支持订阅/分享链接及本地文件)"
content_line "b) \033[36m本地生成配置文件\033[0m(By Providers,推荐!)"
content_line "c) \033[33m在线生成配置文件\033[0m(By Subconverter)"
content_line "d) \033[31m清空提供者列表\033[0m"
content_line "e) \033[36m自定义配置文件\033[0m"
common_back
read -r -p "$COMMON_INPUT_L > " num
case "$num" in
"" | 0)
break
;;
[1-9] | [1-9][0-9])
line=$(cat "$CRASHDIR"/configs/providers.cfg "$CRASHDIR"/configs/providers_uri.cfg 2>/dev/null | sed -n "$num p")
setproviders "$line"
;;
a)
setproviders
;;
b)
if [ -s "$CRASHDIR"/configs/providers.cfg ] || [ -s "$CRASHDIR"/configs/providers_uri.cfg ]; then
if [ "$crashcore" = meta ] || [ "$crashcore" = singboxr ]; then
. "$CRASHDIR"/menus/providers.sh
providers
else
msg_alert "\033[33m仅限Mihomo/singboxr内核使用,请更换内核!\033[0m"
fi
else
msg_alert "请先添加提供者!"
fi
;;
c)
if [ -s "$CRASHDIR"/configs/providers.cfg ] || [ -s "$CRASHDIR"/configs/providers_uri.cfg ]; then
. "$CRASHDIR"/menus/subconverter.sh
subconverter
else
msg_alert "请先添加提供者!"
fi
;;
d)
separator_line "="
content_line "\033[33m警告这将删除所有提供者且无法还原\033[0m"
separator_line "-"
read -r -p "确认清空提供者列表?(1/0) > " res
[ "$res" = 1 ] && {
rm -f "$CRASHDIR"/configs/providers.cfg
rm -f "$CRASHDIR"/configs/providers_uri.cfg
common_success
}
;;
e)
checkcfg=$(cat $CFG_PATH)
. "$CRASHDIR"/menus/override.sh && override
if [ -n "$PID" ]; then
checkcfg_new=$(cat $CFG_PATH)
[ "$checkcfg" != "$checkcfg_new" ] && checkrestart
fi
;;
*)
error_letter
break
;;
esac
done
}
# 添加/管理提供者
setproviders() {
case "$(echo "$@" | cut -d ' ' -f 2)" in
http* | ./providers*)
set -- $@
name=$1
link=$2
interval=$3
interval2=$4
ua=$5
exclude_w=${6#\#}
include_w=${7#\#}
;;
*://*)
set -- $line
name=$1
link_uri=$2
;;
*)
unset name link link_uri interval interval2 ua exclude_w include_w
;;
esac
last_name="$name"
[ -z "$interval" ] && interval=3
[ -z "$interval2" ] && interval2=12
[ -z "$ua" ] && ua='clash.meta'
while true; do
link_info=$(echo "$link$link_uri" | cut -c 1-30)
comp_box "\033[36m支持添加订阅链接/分享链接/本地文件作为提供者\033[0m"
content_line "1) 设置\033[36m名称或代号\033[0m \033[32m$name\033[0m"
content_line "2) 设置\033[32m链接或路径\033[0m \033[36m$link_info...\033[0m"
[ -n "$link" ] &&
content_line "3) 设置\033[33m本地生成覆写\033[0m"
separator_line "-"
content_line "a) \033[36m保存此提供者\033[0m"
[ -n "$link" ] &&
content_line "b) \033[32m本地生成\033[0m仅包含此提供者的配置文件"
echo "$link$link_uri" | grep -q '://' &&
content_line "c) \033[33m在线生成\033[0m仅包含此提供者的配置文件"
echo "$link" | grep -q '^http' &&
content_line "e) 从此订阅链接直接拉取配置文件(不经过订阅转换)"
echo "$link" | grep -q '^./providers' &&
content_line "e) 直接使用此文件作为配置文件(不经过本地生成)"
content_line "d) \033[31m删除此提供者\033[0m"
common_back
read -r -p "请输入对应字母或数字> " input
case "$input" in
"" | 0)
break
;;
1)
separator_line "="
content_line "注意:名称或代号不可重复,且不支持纯数字!"
separator_line "-"
read -p "请输入具体名称或代号 > " text
text=$(echo $text | sed 's/ //g') #去空格
if [ -n "$text" ] && [ -z "$(echo "$text" | grep -E '^[0-9]+$')" ] && ! grep -q "$text" "$CRASHDIR"/configs/providers.cfg; then
name="$text"
else
error_input
fi
;;
2)
separator_line "="
content_line "\033[33m订阅链接\033[0m: https/http开头的clash配置文件订阅链接"
content_line "\033[36m分享链接\033[0m: $URI_EXP"
content_line "\033[33m本地文件\033[0m: 必须放在此目录下:\033[32m$CRASHDIR/providers\033[0m"
content_line "\033[36m Base64 \033[0m: 请直接写入本地文件"
separator_line "-"
list=$(
for f in "$CRASHDIR"/providers/*; do
[ "$f" = "$CRASHDIR"/providers/uri_group ] && continue
[ -f "$f" ] || continue
printf '%s\n' "${f##*/}"
done | sort
)
if [ -n "$list" ];then
list_box "$list"
separator_line "-"
read -r -p "请选择对应文件或输入具体链接 > " text
else
read -r -p "请输入具体链接 > " text
fi
text=$(echo "$text" | sed 's/ //g') #去空格
case "$text" in
http*)
#处理订阅链接
text=$(echo "$text" | sed 's/ *(.*)//g; s/#.*//g') #处理注释及超链接
link="$text"
link_uri=''
common_success
;;
[1-9] | [1-9][0-9])
#处理本地文件
file=$(printf '%s\n' "$list" | sed -n "${text}p")
if [ -s "$CRASHDIR/providers/$file" ]; then
link="$file"
link_uri=''
common_success
else
errornum
fi
;;
*)
#处理分享链接
if [ -n "$(echo $text | grep -E "^$URI_EXP")" ]; then
link_uri=$(echo "$text" | sed 's/#.*//g') # 删除注释
link=''
[ -z "$name" ] && name=$(printf '%b\n' "$(printf '%s' "$text" | sed 's/+/ /g; s/%/\\x/g')" | sed 's/.*#//')
common_success
else
error_input
fi
;;
esac
;;
3)
custproviders
;;
a)
saveproviders && common_success
break
;;
b)
if [ -n "$name" ] && [ -n "$link" ]; then
saveproviders
. "$CRASHDIR/menus/providers_$CORE_TYPE.sh"
gen_providers "$name" "$link" "$interval" "$interval2" "$ua" "#$exclude_w" "#$include_w"
else
content_line "\033[31m$请先完成必填选项!\033[0m"
fi
;;
c)
if [ -n "$name" ] && [ -n "$link$link_uri" ]; then
saveproviders
[ -n "$link" ] && Url="$link"
[ -n "$link_uri" ] && Url=$(echo "$name $link_uri" |awk '{ print ($1=="vmess" ? $2 : $2 "#" $1) }')
Https=''
setconfig Url "'$Url'"
setconfig Https
# 获取在线文件
jump_core_config
else
content_line "\033[31m请先完成必填选项\033[0m"
fi
;;
d)
if [ -n "$name" ] && [ -n "$link" ]; then
sed -i "/^$name /d" "$CRASHDIR"/configs/providers.cfg
content_line "\033[32m$COMMON_SUCCESS\033[0m"
elif [ -n "$name" ] && [ -n "$link_uri" ]; then
sed -i "/^$name /d" "$CRASHDIR"/configs/providers_uri.cfg
content_line "\033[32m$COMMON_SUCCESS\033[0m"
fi
break
;;
e)
if [ -n "$link" ]; then
content_line "注意:\033[31m此功能不兼容“跳过证书验证”功能\033[0m"
content_line "\033[31m请确认你完全理解自己在做什么\033[0m"
read -p "我确认遇到问题可以自行解决(1/0) > " res
[ "$res" = "1" ] && {
file=$(echo "$CRASHDIR/$link" | sed 's|\./||')
if [ -f "$file" ]; then
[ -n "$name" ] && saveproviders
ln -sf "$file" "$CONFIG_PATH"
common_success
break
elif echo "$link" | grep -q '^http'; then
[ -n "$name" ] && saveproviders
Https="$link"
Url=''
setconfig Https "'$Https'"
setconfig Url
# 获取在线文件
jump_core_config
break
else
content_line "\033[31m请先完成必填选项\033[0m"
fi
}
else
content_line "\033[31m请先完成必填选项\033[0m"
sleep 1
fi
;;
*)
error_letter
break
;;
esac
done
}
#保存
saveproviders() {
[ -n "$name" ] && {
[ -s "$CRASHDIR"/configs/providers.cfg ] && sed -i "/^$last_name /d" "$CRASHDIR"/configs/providers.cfg
[ -s "$CRASHDIR"/configs/providers_uri.cfg ] && sed -i "/^$last_name /d" "$CRASHDIR"/configs/providers_uri.cfg
}
if [ -n "$name" ] && [ -n "$link" ]; then
echo "$name $link $interval $interval2 $ua #$exclude_w #$include_w" >>"$CRASHDIR"/configs/providers.cfg
return 0
elif [ -n "$name" ] && [ -n "$link_uri" ]; then
echo "$name $link_uri" >>"$CRASHDIR"/configs/providers_uri.cfg
return 0
else
msg_alert "\033[31m请先完成必填选项\033[0m"
return 1
fi
}
#本地生成覆写
custproviders() {
while true; do
separator_line '-'
content_line "1) 设置\033[33m健康检查间隔\033[0m\t\033[47;30m$interval\033[0m"
content_line "2) 设置\033[36m自动更新间隔\033[0m\t\033[47;30m$interval2\033[0m"
echo "$link" | grep -q '^http' &&
content_line "3) 设置\033[33m虚拟浏览器UA\033[0m\t\033[47;30m$ua\033[0m"
content_line "4) 设置\033[31m排除节点正则\033[0m\t\033[47;30m$exclude_w\033[0m"
content_line "5) 设置\033[32m包含节点正则\033[0m\t\033[47;30m$include_w\033[0m"
common_back
read -r -p "请输入对应数字> " num
case "$num" in
"" | 0)
break
;;
1)
read -p "请输入健康检查间隔(单位:分钟) > " num
if [ -n "$num" ]; then
interval="$num"
else
errornum
fi
;;
2)
read -p "请输入自动更新间隔(单位:小时) > " num
if [ -n "$num" ]; then
interval2="$num"
else
errornum
fi
;;
3)
read -p "请输入浏览器UA(输入0重置) > " text
case "$text" in
0)
include_w='clash.meta'
;;
*)
include_w="$text"
;;
esac
;;
4)
read -p "请输入需要排除的节点关键字(支持正则,不支持空格,输入0删除) > " text
text=$(echo "$text" | sed 's/ //g') #去空格
case "$text" in
0)
exclude_w=''
;;
*)
exclude_w="$text"
;;
esac
;;
5)
read -p "请输入需要筛选使用的节点关键字(支持正则,不支持空格,输入0删除) > " text
text=$(echo "$text" | sed 's/ //g') #去空格
case "$text" in
0)
include_w=''
;;
*)
include_w="$text"
;;
esac
;;
*)
error_letter
break
;;
esac
done
}
# 调用工具在线获取配置文件
jump_core_config() {
. "$CRASHDIR"/starts/core_config.sh && get_core_config
if [ "$?" = 0 ]; then
if [ "$inuserguide" != 1 ]; then
read -p "是否启动服务以使配置文件生效?(1/0) > " res
[ "$res" = 1 ] && start_core || main_menu
exit
fi
fi
}

787
scripts/menus/7_gateway.sh Normal file
View File

@@ -0,0 +1,787 @@
#!/bin/sh
# Copyright (C) Juewuy
[ -n "$__IS_MODULE_7_GATEWAY_LOADED" ] && return
__IS_MODULE_7_GATEWAY_LOADED=1
. "$GT_CFG_PATH"
. "$CRASHDIR"/menus/check_port.sh
. "$CRASHDIR"/libs/gen_base64.sh
# 访问与控制主菜单
gateway() {
while true; do
line_break
separator_line "="
content_line "\033[30;47m访问与控制\033[0m"
separator_line "="
content_line "1) 配置\033[33m公网访问防火墙 \033[32m$fw_wan\033[0m"
content_line "2) 配置\033[36mTelegram专属控制机器人 \033[32m$bot_tg_service\033[0m"
content_line "3) 配置\033[36mDDNS自动域名\033[0m"
[ "$disoverride" != "1" ] && {
content_line "4) 自定义\033[33m公网Vmess入站\033[0m节点 \033[32m$vms_service\033[0m"
content_line "5) 自定义\033[33m公网ShadowSocks入站\033[0m节点 \033[32m$sss_service\033[0m"
content_line "6) 配置\033[36mTailscale内网穿透\033[0m限Singbox \033[32m$ts_service\033[0m"
content_line "7) 配置\033[36mWireguard客户端\033[0m限Singbox \033[32m$wg_service\033[0m"
}
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " num
case "$num" in
"" | 0)
break
;;
1)
line_break
separator_line "="
if [ -n "$(pidof CrashCore)" ] && [ "$firewall_mod" = 'iptables' ]; then
content_line "\033[33m公网访问防火墙需要先停止服务\033[0m"
content_line "是否确认继续:"
separator_line "="
content_line "1) 是"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " res
if [ "$res" = 1 ]; then
"$CRASHDIR"/start.sh stop && set_fw_wan
else
continue
fi
else
set_fw_wan
fi
;;
2)
set_bot_tg
;;
3)
. "$CRASHDIR"/menus/ddns.sh && ddns_menu
;;
4)
set_vmess
;;
5)
set_shadowsocks
;;
6)
if echo "$crashcore" | grep -q 'sing'; then
set_tailscale
else
line_break
separator_line "="
content_line "\033[33m$crashcore内核暂不支持此功能,请先更换内核!\033[0m"
separator_line "="
sleep 1
fi
;;
7)
if echo "$crashcore" | grep -q 'sing'; then
set_wireguard
else
line_break
separator_line "="
content_line "\033[33m$crashcore内核暂不支持此功能,请先更换内核!\033[0m"
separator_line "="
sleep 1
fi
;;
*)
errornum
sleep 1
;;
esac
done
}
# 公网防火墙
set_fw_wan() {
while true; do
[ -z "$fw_wan" ] && fw_wan=ON
line_break
separator_line "="
content_line "\033[31m注意\033[0m如在vps运行还需在vps安全策略对相关端口同时放行"
[ -n "$fw_wan_ports" ] &&
content_line "当前手动放行端口:\033[36m$fw_wan_ports\033[0m"
[ -n "$vms_port$sss_port" ] &&
content_line "当前自动放行端口:\033[36m$vms_port $sss_port\033[0m"
content_line "默认拦截端口:\033[33m$mix_port,$db_port\033[0m"
separator_line "="
content_line "1) 启用/关闭公网防火墙:\033[36m$fw_wan\033[0m"
content_line "2) 添加放行端口(可包含默认拦截端口)"
content_line "3) 移除指定手动放行端口"
content_line "4) 清空全部手动放行端口"
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " num
case $num in
"" | 0)
break
;;
1)
if [ "$fw_wan" = ON ]; then
line_break
separator_line "="
content_line "是否确认关闭防火墙?"
content_line "这会带来极大的安全隐患!"
separator_line "="
content_line "1) 是"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " res
if [ "$res" = 1 ]; then
fw_wan=OFF
else
fw_wan=ON
fi
else
fw_wan=ON
fi
setconfig fw_wan "$fw_wan"
;;
2)
line_break
port_count=$(echo "$fw_wan_ports" | awk -F',' '{print NF}')
if [ "$port_count" -ge 10 ]; then
separator_line "="
content_line "\033[31m最多支持设置放行10个端口请先减少一些\033[0m"
separator_line "="
else
read -r -p "请输入要放行的端口号> " port
if echo ",$fw_wan_ports," | grep -q ",$port,"; then
line_break
separator_line "="
content_line "\033[31m输入错误请勿重复添加\033[0m"
separator_line "="
elif [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
line_break
separator_line "="
content_line "\033[31m输入错误请输入正确的数值(1-65535)\033[0m"
separator_line "="
else
fw_wan_ports=$(echo "$fw_wan_ports,$port" | sed "s/^,//")
setconfig fw_wan_ports "$fw_wan_ports"
fi
fi
sleep 1
;;
3)
while true; do
line_break
separator_line "="
content_line "请直接输入要移除的端口号"
content_line "或输入 0 返回上级菜单"
separator_line "="
read -r -p "请输入> " port
if [ "$port" = 0 ]; then
break
elif echo ",$fw_wan_ports," | grep -q ",$port,"; then
if [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
line_break
separator_line "="
content_line "\033[31m输入错误\033[0m"
content_line "\033[31m请输入正确的数值(1-65535)\033[0m"
separator_line "="
sleep 1
else
fw_wan_ports=$(echo ",$fw_wan_ports," | sed "s/,$port//; s/^,//; s/,$//")
setconfig fw_wan_ports "$fw_wan_ports"
break
fi
else
line_break
separator_line "="
content_line "\033[31m输入错误\033[0m"
content_line "\033[31m请输入已添加过的端口\033[0m"
separator_line "="
sleep 1
fi
done
;;
4)
fw_wan_ports=''
setconfig fw_wan_ports
line_break
separator_line "="
content_line "\033[32m操作成功\033[0m"
separator_line "="
sleep 1
;;
*)
errornum
sleep 1
;;
esac
done
}
# tg_BOT相关
set_bot_tg_config() {
setconfig TG_TOKEN "$TOKEN" "$GT_CFG_PATH"
setconfig TG_CHATID "$chat_ID" "$GT_CFG_PATH"
# 设置机器人快捷命令
JSON=$(
cat <<EOF
{
"commands": [
{"command": "$my_alias", "description": "呼出ShellCrash菜单"},
{"command": "help", "description": "查看帮助"}
]
}
EOF
)
TEXT="已完成Telegram机器人设置请使用 /$my_alias 呼出功能菜单!"
. "$CRASHDIR"/libs/web_json.sh
bot_api="https://api.telegram.org/bot$TOKEN"
web_json_post "$bot_api/setMyCommands" "$JSON"
web_json_post "$bot_api/sendMessage" '{"chat_id":"'"$chat_ID"'","text":"'"$TEXT"'","parse_mode":"Markdown"}'
line_break
separator_line "="
content_line "\033[32m$TEXT\033[0m"
separator_line "="
}
set_bot_tg_init() {
. "$CRASHDIR"/menus/bot_tg_bind.sh && private_bot && set_bot
if [ "$?" = 0 ]; then
set_bot_tg_config
return 0
else
return 1
fi
}
set_bot_tg_service() {
if [ "$bot_tg_service" = ON ]; then
bot_tg_service=OFF
. "$CRASHDIR"/menus/bot_tg_service.sh && bot_tg_stop
else
bot_tg_service=ON
[ -n "$(pidof CrashCore)" ] && . "$CRASHDIR"/menus/bot_tg_service.sh && bot_tg_start
fi
setconfig bot_tg_service "$bot_tg_service"
}
set_bot_tg() {
while true; do
[ -n "$ts_auth_key" ] && ts_auth_key_info='已设置'
[ -n "$TG_CHATID" ] && TG_CHATID_info='已绑定'
line_break
separator_line "="
content_line "\033[31m注意\033[0m由于网络环境原因此机器人仅限服务启动时运行"
separator_line "="
content_line "1) 启用关闭TG-BOT服务 \033[32m$bot_tg_service\033[0m"
content_line "2) TG-BOT绑定设置 \033[32m$TG_CHATID_info\033[0m"
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " num
case "$num" in
"" | 0)
break
;;
1)
. "$GT_CFG_PATH"
if [ -n "$TG_CHATID" ]; then
set_bot_tg_service
else
line_break
separator_line "="
content_line "\033[31m请先绑定TG-BOT\033[0m"
separator_line "="
fi
sleep 1
;;
2)
if [ -n "$chat_ID" ] && [ -n "$push_TG" ] && [ "$push_TG" != 'publictoken' ]; then
line_break
separator_line "="
content_line "检测到已经绑定了TG推送BOT"
content_line "是否直接使用:"
separator_line "="
content_line "1) 是"
content_line "0) 否"
separator_line "="
read -r -p "请输入对应标号> " res
if [ "$res" = 1 ]; then
TOKEN="$push_TG"
set_bot_tg_config
continue
fi
fi
set_bot_tg_init
;;
*)
errornum
sleep 1
;;
esac
done
}
# 自定义入站
set_vmess() {
while true; do
line_break
separator_line "="
content_line "\033[31m注意\033[0m"
content_line "设置的端口会添加到公网访问防火墙并自动放行!"
content_line "脚本只提供基础功能,更多需求请用自定义配置文件功能!"
content_line "\033[31m切勿用于搭建违法翻墙节点违者后果自负\033[0m"
separator_line "="
content_line "1) \033[32m启用/关闭\033[0mVmess入站 \033[32m$vms_service\033[0m"
content_line "2) 设置\033[36m监听端口\033[0m \033[36m$vms_port\033[0m"
content_line "3) 设置\033[33mWS-path可选\033[0m \033[33m$vms_ws_path\033[0m"
content_line "4) 设置\033[36m秘钥-uuid\033[0m \033[36m$vms_uuid\033[0m"
content_line "5) 一键生成\033[32m随机秘钥\033[0m"
gen_base64 1 >/dev/null 2>&1 &&
content_line "6) 设置\033[36m混淆host可选\033[0m \033[33m$vms_host\033[0m"
content_line "7) 一键生成\033[32m分享链接\033[0m"
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " num
case "$num" in
"" | 0)
break
;;
1)
if [ "$vms_service" = ON ]; then
vms_service=OFF
setconfig vms_service "$vms_service"
else
if [ -n "$vms_port" ] && [ -n "$vms_uuid" ]; then
vms_service=ON
setconfig vms_service "$vms_service"
else
line_break
separator_line "="
content_line "\033[31m请先完成必选设置\033[0m"
separator_line "="
sleep 1
fi
fi
;;
2)
line_break
read -r -p "请输入端口号输入0删除> " text
if [ "$text" = 0 ]; then
vms_port=''
setconfig vms_port "" "$GT_CFG_PATH"
elif check_port "$text"; then
vms_port="$text"
setconfig vms_port "$text" "$GT_CFG_PATH"
else
sleep 1
fi
;;
3)
line_break
read -r -p "请输入ws-path路径输入0删除> " text
if [ "$text" = 0 ]; then
vms_ws_path=''
setconfig vms_ws_path "" "$GT_CFG_PATH"
elif echo "$text" | grep -qE '^/'; then
vms_ws_path="$text"
setconfig vms_ws_path "$text" "$GT_CFG_PATH"
else
line_break
separator_line "="
content_line "\033[31m不是合法的path路径必须以【/】开头!\033[0m"
separator_line "="
sleep 1
fi
;;
4)
line_break
read -r -p "请输入UUID输入0删除> " text
if [ "$text" = 0 ]; then
vms_uuid=''
setconfig vms_uuid "" "$GT_CFG_PATH"
elif echo "$text" | grep -qiE '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'; then
vms_uuid="$text"
setconfig vms_uuid "$text" "$GT_CFG_PATH"
else
line_break
separator_line "="
content_line "\033[31m不是合法的UUID格式请重新输入或使用随机生成功能\033[0m"
separator_line "="
sleep 1
fi
;;
5)
vms_uuid=$(cat /proc/sys/kernel/random/uuid)
setconfig vms_uuid "$vms_uuid" "$GT_CFG_PATH"
sleep 1
;;
6)
line_break
read -r -p "请输入免流混淆host输入0删除> " text
if [ "$text" = 0 ]; then
vms_host=''
setconfig vms_host "" "$GT_CFG_PATH"
else
vms_host="$text"
setconfig vms_host "$text" "$GT_CFG_PATH"
fi
;;
7)
line_break
read -r -p "请输入本机公网IP(4/6)或域名> " host_wan
if [ -n "$host_wan" ] && [ -n "$vms_port" ] && [ -n "$vms_uuid" ]; then
[ -n "$vms_ws_path" ] && vms_net=ws
vms_json=$(
cat <<EOF
{
"v": "2",
"ps": "ShellCrash_vms_in",
"add": "$host_wan",
"port": "$vms_port",
"id": "$vms_uuid",
"aid": "0",
"type": "auto",
"net": "$vms_net",
"path": "$vms_ws_path",
"host": "$vms_host"
}
EOF
)
vms_link="vmess://$(gen_base64 "$vms_json")"
line_break
echo -e "你的分享链接是(请勿随意分享给他人):\n\033[32m$vms_link\033[0m"
else
line_break
separator_line "="
content_line "\033[31m请先完成必选设置\033[0m"
separator_line "="
fi
sleep 1
;;
*)
errornum
sleep 1
;;
esac
done
}
set_shadowsocks() {
while true; do
line_break
separator_line "="
content_line "\033[31m注意\033[0m"
content_line "设置的端口会添加到公网访问防火墙并自动放行!"
content_line "脚本只提供基础功能,更多需求请用自定义配置文件功能!"
content_line "\033[31m切勿用于搭建违法翻墙节点违者后果自负\033[0m"
separator_line "="
content_line "1) \033[32m启用/关闭\033[0mShadowSocks入站 \033[32m$sss_service\033[0m"
content_line "2) 设置\033[36m监听端口\033[0m \033[36m$sss_port\033[0m"
content_line "3) 选择\033[33m加密协议\033[0m \033[33m$sss_cipher\033[0m"
content_line "4) 设置\033[36mpassword\033[0m \033[36m$sss_pwd\033[0m"
gen_base64 1 >/dev/null 2>&1 &&
content_line "5) 一键生成分享链接"
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " num
case "$num" in
"" | 0)
break
;;
1)
if [ "$sss_service" = ON ]; then
sss_service=OFF
setconfig sss_service "$sss_service"
else
if [ -n "$sss_port" ] && [ -n "$sss_cipher" ] && [ -n "$sss_pwd" ]; then
sss_service=ON
setconfig sss_service "$sss_service"
else
line_break
separator_line "="
content_line "\033[31m请先完成必选设置\033[0m"
separator_line "="
sleep 1
fi
fi
;;
2)
line_break
read -r -p "请输入端口号输入0删除> " text
if [ "$text" = 0 ]; then
sss_port=''
setconfig sss_port "" "$GT_CFG_PATH"
elif check_port "$text"; then
sss_port="$text"
setconfig sss_port "$text" "$GT_CFG_PATH"
else
sleep 1
fi
;;
3)
line_break
separator_line "="
content_line "请选择要使用的加密协议:"
separator_line "="
content_line "1) \033[32mxchacha20-ietf-poly1305\033[0m"
content_line "2) \033[32mchacha20-ietf-poly1305\033[0m"
content_line "3) \033[32maes-128-gcm\033[0m"
content_line "4) \033[32maes-256-gcm\033[0m"
gen_random 1 >/dev/null && {
content_line ""
content_line " - - - - - - -\033[31m注意\033[0m- - - - - - -"
content_line " 2022系列加密必须使用随机生成的password"
content_line "5) \033[32m2022-blake3-chacha20-poly1305\033[0m"
content_line "6) \033[32m2022-blake3-aes-128-gcm\033[0m"
content_line "7) \033[32m2022-blake3-aes-256-gcm\033[0m"
}
content_line ""
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " num
case "$num" in
0) ;;
1)
sss_cipher=xchacha20-ietf-poly1305
sss_pwd=$(gen_random 16)
;;
2)
sss_cipher=chacha20-ietf-poly1305
sss_pwd=$(gen_random 16)
;;
3)
sss_cipher=aes-128-gcm
sss_pwd=$(gen_random 16)
;;
4)
sss_cipher=aes-256-gcm
sss_pwd=$(gen_random 16)
;;
5)
sss_cipher=2022-blake3-chacha20-poly1305
sss_pwd=$(gen_random 32)
;;
6)
sss_cipher=2022-blake3-aes-128-gcm
sss_pwd=$(gen_random 16)
;;
7)
sss_cipher=2022-blake3-aes-256-gcm
sss_pwd=$(gen_random 32)
;;
*)
errornum
sleep 1
;;
esac
setconfig sss_cipher "$sss_cipher" "$GT_CFG_PATH"
setconfig sss_pwd "$sss_pwd" "$GT_CFG_PATH"
;;
4)
line_break
if echo "$sss_cipher" | grep -q '2022-blake3'; then
separator_line "="
content_line "\033[31m注意\033[0m2022系列加密必须使用脚本随机生成的password"
separator_line "="
sleep 1
else
read -r -p "请输入秘钥输入0删除> " text
[ "$text" = 0 ] && sss_pwd='' || sss_pwd="$text"
setconfig sss_pwd "$text" "$GT_CFG_PATH"
fi
;;
5)
line_break
read -r -p "请输入本机公网IP(4/6)或域名> " text
if [ -n "$text" ] && [ -n "$sss_port" ] && [ -n "$sss_cipher" ] && [ -n "$sss_pwd" ]; then
ss_link="ss://$(gen_base64 "$sss_cipher":"$sss_pwd")@${text}:${sss_port}#ShellCrash_ss_in"
line_break
echo -e "你的分享链接是(请勿随意分享给他人):\n\033[32m$ss_link\033[0m"
else
line_break
separator_line "="
content_line "\033[31m请先完成必选设置\033[0m"
separator_line "="
fi
sleep 1
;;
*)
errornum
sleep 1
;;
esac
done
}
# 自定义端点
set_tailscale() {
while true; do
[ -n "$ts_auth_key" ] && ts_auth_key_info='*********'
line_break
separator_line "="
content_line "\033[31m注意\033[0m脚本默认内核为了节约内存没有编译Tailscale模块\n如需使用请先前往自定义内核更新完整版内核文件"
content_line "创建秘钥:\033[32;4mhttps://login.tailscale.com/admin/settings/keys\033[0m"
content_line "访问非本机目标需允许通告:\033[32;4mhttps://login.tailscale.com\033[0m"
content_line "访问非本机目标需在终端设置使用Subnet或EXIT-NODE模式"
separator_line "="
content_line "1) \033[32m启用/关闭\033[0mTailscale服务 \033[32m$ts_service\033[0m"
content_line "2) 设置\033[36m秘钥\033[0mAuth Key $ts_auth_key_info"
content_line "3) 通告路由\033[33m内网地址\033[0mSubnet \033[36m$ts_subnet\033[0m"
content_line "4) 通告路由\033[31m全部流量\033[0mEXIT-NODE \033[36m$ts_exit_node\033[0m"
content_line "5) 设置\033[36m设备名称\033[0m可选 $ts_hostname"
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " num
case "$num" in
"" | 0)
break
;;
1)
if [ -n "$ts_auth_key" ]; then
[ "$ts_service" = ON ] && ts_service=OFF || ts_service=ON
setconfig ts_service "$ts_service"
else
line_break
separator_line "="
content_line "\033[31m请先设置秘钥\033[0m"
separator_line "="
sleep 1
fi
;;
2)
line_break
read -r -p "请输入秘钥输入0删除> " text
[ "$text" = 0 ] && unset ts_auth_key ts_auth_key_info || ts_auth_key="$text"
setconfig ts_auth_key "$ts_auth_key" "$GT_CFG_PATH"
;;
3)
[ "$ts_subnet" = true ] && ts_subnet=false || ts_subnet=true
setconfig ts_subnet "$ts_subnet" "$GT_CFG_PATH"
;;
4)
if [ "$ts_exit_node" = true ]; then
ts_exit_node=false
else
ts_exit_node=true
line_break
separator_line "="
content_line "\033[31m注意\033[0m目前exitnode的官方DNS有bug要么启用域名嗅探并禁用TailscaleDNS\n要么必须在网页设置Globalname servers为分配的本设备子网IP且启用override"
separator_line "="
sleep 3
fi
setconfig ts_exit_node "$ts_exit_node" "$GT_CFG_PATH"
;;
5)
line_break
separator_line "="
content_line "请直接输入希望在Tailscale显示的设备名称"
content_line "或输入 0 返回上级菜单"
separator_line "="
read -r -p "请输入> " ts_hostname
if [ "$ts_hostname" != 0 ]; then
setconfig ts_hostname "$ts_hostname" "$GT_CFG_PATH"
fi
;;
*)
errornum
sleep 1
;;
esac
done
}
set_wireguard() {
while true; do
if [ -n "$wg_public_key" ]; then
wgp_key_info='*********'
else
unset wgp_key_info
fi
if [ -n "$wg_private_key" ]; then
wgv_key_info='*********'
else
unset wgv_key_info
fi
if [ -n "$wg_pre_shared_key" ]; then
wgpsk_key_info='*********'
else
unset wgpsk_key_info
fi
line_break
separator_line "="
content_line "\033[31m注意\033[0m脚本默认内核为了节约内存没有编译WireGuard模块\n如需使用请先前往自定义内核更新完整版内核文件"
separator_line "="
content_line "1) \033[32m启用/关闭\033[0mWireguard服务 \033[32m$wg_service\033[0m"
content_line ""
content_line "2) 设置\033[36mEndpoint地址\033[0m \033[36m$wg_server\033[0m"
content_line "3) 设置\033[36mEndpoint端口\033[0m \033[36m$wg_port\033[0m"
content_line "4) 设置\033[36m公钥-PublicKey\033[0m \033[36m$wgp_key_info\033[0m"
content_line "5) 设置\033[36m密钥-PresharedKey\033[0m \033[36m$wgpsk_key_info\033[0m"
content_line ""
content_line "6) 设置\033[33m私钥-PrivateKey\033[0m \033[33m$wgv_key_info\033[0m"
content_line "7) 设置\033[33m组网IPV4地址\033[0m \033[33m$wg_ipv4\033[0m"
content_line "8) 可选\033[33m组网IPV6地址\033[0m \033[33m$wg_ipv6\033[0m"
content_line ""
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " num
case "$num" in
"" | 0)
break
;;
1)
if [ -n "$wg_server" ] && [ -n "$wg_port" ] && [ -n "$wg_public_key" ] && [ -n "$wg_pre_shared_key" ] && [ -n "$wg_private_key" ] && [ -n "$wg_ipv4" ]; then
[ "$wg_service" = ON ] && wg_service=OFF || wg_service=ON
setconfig wg_service "$wg_service"
else
line_break
separator_line "="
content_line "\033[31m请先完成必选设置\033[0m"
separator_line "="
sleep 1
fi
;;
[1-8])
line_break
read -r -p "请输入相应内容回车或0删除> " text
[ "$text" = 0 ] && text=''
case "$num" in
2)
wg_server="$text"
setconfig wg_server "$text" "$GT_CFG_PATH"
;;
3)
wg_port="$text"
setconfig wg_port "$text" "$GT_CFG_PATH"
;;
4)
wg_public_key="$text"
setconfig wg_public_key "$text" "$GT_CFG_PATH"
;;
5)
wg_pre_shared_key="$text"
setconfig wg_pre_shared_key "$text" "$GT_CFG_PATH"
;;
6)
wg_private_key="$text"
setconfig wg_private_key "$text" "$GT_CFG_PATH"
;;
7)
wg_ipv4="$text"
setconfig wg_ipv4 "$text" "$GT_CFG_PATH"
;;
8)
wg_ipv6="$text"
setconfig wg_ipv6 "$text" "$GT_CFG_PATH"
;;
esac
;;
*)
errornum
sleep 1
;;
esac
done
}

889
scripts/menus/8_tools.sh Normal file
View File

@@ -0,0 +1,889 @@
#!/bin/sh
# Copyright (C) Juewuy
[ -n "$__IS_MODULE_8_TOOLS_LOADED" ] && return
__IS_MODULE_8_TOOLS_LOADED=1
. "$CRASHDIR"/libs/logger.sh
. "$CRASHDIR"/libs/web_get_bin.sh
stop_iptables() {
iptables -w -t nat -D PREROUTING -p tcp -m multiport --dports "$ssh_port" -j REDIRECT --to-ports 22 >/dev/null 2>&1
ip6tables -w -t nat -A PREROUTING -p tcp -m multiport --dports "$ssh_port" -j REDIRECT --to-ports 22 >/dev/null 2>&1
}
ssh_tools() {
while true; do
[ -n "$(cat /etc/firewall.user 2>&1 | grep '启用外网访问SSH服务')" ] && ssh_ol=禁止 || ssh_ol=开启
[ -z "$ssh_port" ] && ssh_port=10022
line_break
separator_line "="
content_line "\033[33m此功能仅针对使用Openwrt系统的设备生效且不依赖服务\033[0m"
content_line "\033[31m本功能不支持红米AX6S等镜像化系统设备请勿尝试\033[0m"
separator_line "="
content_line "1) \033[32m修改\033[0m外网访问端口\033[36m$ssh_port\033[0m"
content_line "2) \033[32m修改\033[0mSSH访问密码(请连续输入2次后回车)"
content_line "3) \033[33m$ssh_ol\033[0m外网访问SSH"
content_line ""
content_line "0) 返回上级菜单 \033[0m"
separator_line "="
read -r -p "请输入对应标号> " num
case "$num" in
"" | 0)
break
;;
1)
line_break
read -r -p "请输入端口号(1000-65535)> " num
if [ -z "$num" ]; then
errornum
elif [ "$num" -gt 65535 ] || [ "$num" -le 999 ]; then
line_break
separator_line "="
content_line "\033[31m输入错误请输入正确的数值(1000-65535)\033[0m"
separator_line "="
elif [ -n "$(netstat -ntul | grep :$num)" ]; then
line_break
separator_line "="
content_line "\033[31m当前端口已被其他进程占用请重新输入\033[0m"
separator_line "="
else
ssh_port=$num
setconfig ssh_port "$ssh_port"
sed -i "/启用外网访问SSH服务/d" /etc/firewall.user
stop_iptables
line_break
separator_line "="
content_line "\033[32m设置成功请重新开启外网访问SSH功能"
separator_line "="
fi
sleep 1
;;
2)
passwd
sleep 1
;;
3)
line_break
if [ "$ssh_ol" = "开启" ]; then
iptables -w -t nat -A PREROUTING -p tcp -m multiport --dports "$ssh_port" -j REDIRECT --to-ports 22
[ -n "$(ckcmd ip6tables)" ] && ip6tables -w -t nat -A PREROUTING -p tcp -m multiport --dports "$ssh_port" -j REDIRECT --to-ports 22
echo "iptables -w -t nat -A PREROUTING -p tcp -m multiport --dports $ssh_port -j REDIRECT --to-ports 22 #启用外网访问SSH服务" >>/etc/firewall.user
[ -n "$(ckcmd ip6tables)" ] && echo "ip6tables -w -t nat -A PREROUTING -p tcp -m multiport --dports $ssh_port -j REDIRECT --to-ports 22 #启用外网访问SSH服务" >>/etc/firewall.user
separator_line "="
content_line "已开启外网访问SSH功能"
separator_line "="
else
sed -i "/启用外网访问SSH服务/d" /etc/firewall.user
stop_iptables
separator_line "="
content_line "已禁止外网访问SSH"
separator_line "="
fi
break
;;
*)
errornum
sleep 1
break
;;
esac
done
}
# 工具与优化
tools() {
while true; do
# 获取设置默认显示
grep -qE "^\s*[^#].*otapredownload" /etc/crontabs/root >/dev/null 2>&1 && mi_update=禁用 || mi_update=启用
[ "$mi_mi_autoSSH" = "已配置" ] && mi_mi_autoSSH_type=32m已配置 || mi_mi_autoSSH_type=31m未配置
[ -f "$CRASHDIR"/tools/tun.ko ] && mi_tunfix=32mON || mi_tunfix=31mOFF
line_break
separator_line "="
content_line "\033[30;47m工具与优化\033[0m"
separator_line "="
content_line "\033[33m本页工具可能无法兼容全部Linux设备请酌情使用\033[0m"
content_line "磁盘占用/所在目录:"
content_line "$(du -sh "$CRASHDIR")"
separator_line "="
content_line "1) ShellCrash\033[33m测试菜单\033[0m"
content_line "2) ShellCrash\033[32m新手引导\033[0m"
content_line "3) \033[36m日志及推送工具\033[0m"
[ -f /etc/firewall.user ] && content_line "4) \033[32m配置\033[0m外网访问SSH"
[ -x /usr/sbin/otapredownload ] && content_line "5) \033[33m$mi_update\033[0m小米系统自动更新"
[ "$systype" = "mi_snapshot" ] && content_line "6) 小米设备软固化SSH ———— \033[$mi_mi_autoSSH_type \033[0m"
[ "$systype" = "mi_snapshot" ] && content_line "8) 小米设备Tun模块修复 ———— \033[$mi_tunfix \033[0m"
content_line ""
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " num
case "$num" in
"" | 0)
break
;;
1)
testcommand
;;
2)
. "$CRASHDIR"/menus/userguide.sh && userguide
break
;;
3)
log_pusher
;;
4)
ssh_tools
sleep 1
;;
5)
if [ -x /usr/sbin/otapredownload ]; then
if [ "$mi_update" = "禁用" ]; then
grep -q "otapredownload" /etc/crontabs/root &&
sed -i "/^[^\#]*otapredownload/ s/^/#/" /etc/crontabs/root ||
echo "#15 3,4,5 * * * /usr/sbin/otapredownload >/dev/null 2>&1" >>/etc/crontabs/root
else
grep -q "otapredownload" /etc/crontabs/root &&
sed -i "/^\s*#.*otapredownload/ s/^\s*#//" /etc/crontabs/root ||
echo "15 3,4,5 * * * /usr/sbin/otapredownload >/dev/null 2>&1" >>/etc/crontabs/root
fi
line_break
separator_line "="
content_line "已\033[33m$mi_update\033[0m小米路由器的自动更新如未生效请在官方APP中同步设置"
separator_line "="
sleep 1
fi
;;
6)
if [ "$systype" = "mi_snapshot" ]; then
mi_autoSSH
else
line_break
separator_line "="
content_line "不支持的设备!"
separator_line "="
fi
;;
7)
line_break
separator_line "="
if [ ! -f "$CRASHDIR"/tools/ShellDDNS.sh ]; then
content_line "正在获取在线脚本......"
get_bin "$TMPDIR"/ShellDDNS.sh tools/ShellDDNS.sh
if [ "$?" = "0" ]; then
mv -f "$TMPDIR"/ShellDDNS.sh "$CRASHDIR"/tools/ShellDDNS.sh
. "$CRASHDIR"/tools/ShellDDNS.sh
else
content_line "\033[31m文件下载失败\033[0m"
separator_line "="
fi
else
. "$CRASHDIR"/tools/ShellDDNS.sh
fi
sleep 1
;;
8)
line_break
separator_line "="
if [ -f "$CRASHDIR"/tools/tun.ko ]; then
content_line "是否禁用此功能并移除相关补丁:"
separator_line "="
content_line "1) 是"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " res
[ "$res" = 1 ] && {
rm -rf "$CRASHDIR"/tools/tun.ko
line_break
separator_line "="
content_line "\033[33m补丁文件已移除请立即重启设备以防止出错\033[0m"
separator_line "="
}
elif ckcmd modinfo && [ -z "$(modinfo tun)" ]; then
content_line "\033[33m本功能需要修改系统文件不保证没有任何风险\033[0m"
content_line "\033[33m本功能采集的Tun模块并不一定适用于你的设备\033[0m"
separator_line "="
content_line "1) 我已知晓,出现问题会自行承担!"
content_line "0) 返回上级菜单"
eparator_line "="
read -r -p "请输入对应标号> " res
if [ "$res" = 1 ]; then
line_break
eparator_line "="
content_line "正在连接服务器获取Tun模块补丁文件......"
get_bin "$TMPDIR"/tun.ko bin/fix/tun.ko
if [ "$?" = "0" ]; then
mv -f "$TMPDIR"/tun.ko "$CRASHDIR"/tools/tun.ko &&
/data/shellcrash_init.sh tunfix &&
content_line "\033[32m设置成功请重启服务\033[0m"
else
content_line "\033[31m文件下载失败请重试\033[0m"
fi
eparator_line "="
else
continue
fi
else
content_line "\033[31m当前设备无需设置请勿尝试\033[0m"
separator_line "="
sleep 1
fi
;;
*)
errornum
sleep 1
;;
esac
done
}
mi_autoSSH() {
line_break
separator_line "="
content_line "\033[33m本功能使用软件命令进行固化不保证100%成功!\033[0m"
content_line "\033[33m如有问题请加群反馈\033[36;4mhttps://t.me/ShellClash\033[0m"
content_line ""
content_line "请输入需要还原的SSH密码不影响当前密码"
content_line "(回车可跳过)"
separator_line "="
read -r -p "请输入> " mi_mi_autoSSH_pwd
mi_mi_autoSSH=已配置
cp -f /etc/dropbear/dropbear_rsa_host_key "$CRASHDIR"/configs/dropbear_rsa_host_key 2>/dev/null
cp -f /etc/dropbear/authorized_keys "$CRASHDIR"/configs/authorized_keys 2>/dev/null
ckcmd nvram && {
nvram set ssh_en=1
nvram set telnet_en=1
nvram set uart_en=1
nvram set boot_wait=on
nvram commit
}
line_break
separator_line "="
content_line "\033[32m设置成功\033[0m"
separator_line "="
setconfig mi_mi_autoSSH $mi_mi_autoSSH
setconfig mi_mi_autoSSH_pwd "$mi_mi_autoSSH_pwd"
sleep 1
}
# 日志菜单
log_pusher() {
while true; do
[ -n "$push_TG" ] && stat_TG=32mON || stat_TG=33mOFF
[ -n "$push_Deer" ] && stat_Deer=32mON || stat_Deer=33mOFF
[ -n "$push_bark" ] && stat_bark=32mON || stat_bark=33mOFF
[ -n "$push_Po" ] && stat_Po=32mON || stat_Po=33mOFF
[ -n "$push_PP" ] && stat_PP=32mON || stat_PP=33mOFF
[ -n "$push_SynoChat" ] && stat_SynoChat=32mON || stat_SynoChat=33mOFF
[ -n "$push_Gotify" ] && stat_Gotify=32mON || stat_Gotify=33mOFF
[ "$task_push" = 1 ] && stat_task=32mON || stat_task=33mOFF
[ -n "$device_name" ] && device_s=32m$device_name || device_s=33m未设置
line_break
separator_line "="
content_line "1) Telegram推送 ——\033[$stat_TG\033[0m"
content_line "2) PushDeer推送 ——\033[$stat_Deer\033[0m"
content_line "3) Bark推送-IOS ——\033[$stat_bark\033[0m"
content_line "4) Passover推送 ——\033[$stat_Po\033[0m"
content_line "5) PushPlus推送 ——\033[$stat_PP\033[0m"
content_line "6) SynoChat推送 ——\033[$stat_SynoChat\033[0m"
content_line "7) Gotify推送 ——\033[$stat_Gotify\033[0m"
content_line ""
content_line "a) 查看\033[36m运行日志\033[0m"
content_line "b) 推送任务日志 ——\033[$stat_task\033[0m"
content_line "c) 设置设备名称 ——\033[$device_s\033[0m"
content_line "d) 清空日志文件"
content_line ""
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " num
case "$num" in
"" | 0)
break
;;
1)
line_break
separator_line "="
if [ -n "$push_TG" ]; then
content_line "是否确认关闭TG日志推送"
separator_line "="
content_line "1) 是"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " res
if [ "$res" = 1 ]; then
push_TG=
chat_ID=
setconfig push_TG
setconfig chat_ID
else
continue
fi
else
# echo -e "\033[33m详细设置指南请参考 https://juewuy.github.io/ \033[0m"
. "$CRASHDIR"/menus/bot_tg_bind.sh
chose_bot() {
content_line "1) 使用公共机器人 ——不依赖内核服务"
content_line "2) 使用私人机器人 ——需要额外申请"
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " num
case "$num" in
0)
return 0
;;
1)
public_bot
set_bot && tg_push_token || chose_bot
;;
2)
private_bot
set_bot && tg_push_token || chose_bot
;;
*)
errornum
;;
esac
}
chose_bot
fi
;;
2)
line_break
separator_line "="
if [ -n "$push_Deer" ]; then
content_line "是否确认关闭PushDeer日志推送"
separator_line "="
content_line "1) 是"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " res
if [ "$res" = 1 ]; then
push_Deer=
setconfig push_Deer
else
continue
fi
else
# echo -e "\033[33m详细设置指南请参考 https://juewuy.github.io/ \033[0m"
content_line "1. 请先前往 \033[32;4mhttp://www.pushdeer.com/official.html\033[0m 扫码安装快应用或下载APP"
content_line "2. 打开快应用/APP并完成登陆"
content_line "3. \033[33m切换到「设备」标签页点击右上角的加号注册当前设备\033[0m"
content_line "4. \033[36m切换到「秘钥」标签页点击右上角的加号创建一个秘钥并复制\033[0m"
separator_line "="
content_line "请直接输入你复制的秘钥"
content_line "或输入 0 返回上级菜单"
separator_line "="
read -r -p "请输入> " url
if [ "$url" = 0 ]; then
continue
elif [ -n "$url" ]; then
push_Deer=$url
setconfig push_Deer "$url"
logger "已完成PushDeer日志推送设置" 32
else
line_break
separator_line "="
content_line "\033[31m输入错误请重新输入\033[0m"
separator_line "="
fi
sleep 1
fi
;;
3)
line_break
separator_line "="
if [ -n "$push_bark" ]; then
content_line "是否确认关闭Bark日志推送"
separator_line "="
content_line "1) 是"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " res
if [ "$res" = 1 ]; then
push_bark=
bark_param=
setconfig push_bark
setconfig bark_param
else
continue
fi
else
# echo -e "\033[33m详细设置指南请参考 https://juewuy.github.io/ \033[0m"
content_line "\033[33mBark推送仅支持IOS系统其他平台请使用其他推送方式\033[0m"
content_line "\033[32m请安装Bark-IOS客户端并在客户端中找到专属推送链接\033[0m"
separator_line "="
content_line "请直接输入你的Bark推送链接"
content_line "或输入 0 返回上级菜单"
separator_line "="
read -r -p "请输入> " url
if [ "$url" = 0 ]; then
continue
elif [ -n "$url" ]; then
push_bark=$url
setconfig push_bark "$url"
logger "已完成Bark日志推送设置" 32
else
line_break
separator_line "="
content_line "\033[31m输入错误请重新输入\033[0m"
separator_line "="
fi
sleep 1
fi
;;
4)
line_break
separator_line "="
if [ -n "$push_Po" ]; then
content_line "是否确认关闭Pushover日志推送"
separator_line "="
content_line "1) 是"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " res
if [ "$res" = 1 ]; then
push_Po=
push_Po_key=
setconfig push_Po
setconfig push_Po_key
else
continue
fi
else
# echo -e "\033[33m详细设置指南请参考 https://juewuy.github.io/ \033[0m"
content_line "请先通过 \033[32;4mhttps://pushover.net/\033[0m 注册账号并获取\033[36mUser Key\033[0m"
content_line ""
content_line "请直接请输入你的User Key"
content_line "或输入 0 返回上级菜单"
separator_line "="
read -r -p "请输入> " key
if [ "$key" = 0 ]; then
continue
elif [ -n "$key" ]; then
line_break
separator_line "="
content_line "\033[33m请检查注册邮箱完成账户验证\033[0m"
read -r -p "我已经验证完成(1/0)> "
separator_line "="
line_break
separator_line "="
content_line "请通过 \033[32;4mhttps://pushover.net/apps/build\033[0m 生成\033[36mAPI Token\033[0m"
separator_line "="
read -r -p "请输入你的API Token> " Token
if [ -n "$Token" ]; then
push_Po=$Token
push_Po_key=$key
setconfig push_Po "$Token"
setconfig push_Po_key "$key"
logger "已完成Passover日志推送设置" 32
else
line_break
separator_line "="
content_line "\033[31m输入错误请重新输入\033[0m"
separator_line "="
fi
else
line_break
separator_line "="
content_line "\033[31m输入错误请重新输入\033[0m"
separator_line "="
fi
sleep 1
fi
;;
5)
line_break
separator_line "="
if [ -n "$push_PP" ]; then
content_line "是否确认关闭PushPlus日志推送"
separator_line "="
content_line "1) 是"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " res
if [ "$res" = 1 ]; then
push_PP=
setconfig push_PP
else
continue
fi
else
# echo -e "\033[33m详细设置指南请参考 https://juewuy.github.io/ \033[0m"
content_line "请先通过 \033[32;4mhttps://www.pushplus.plus/push1.html\033[0m 注册账号并获取\033[36mtoken\033[0m"
separator_line "="
content_line "请直接输入你的token"
content_line "或输入 0 返回上级菜单"
separator_line "="
read -r -p "请输入> " Token
if [ "$Token" = 0 ]; then
continue
elif [ -n "$Token" ]; then
push_PP=$Token
setconfig push_PP "$Token"
logger "已完成PushPlus日志推送设置" 32
else
line_break
separator_line "="
content_line "\033[31m输入错误请重新输入\033[0m"
separator_line "="
fi
sleep 1
fi
;;
6)
line_break
if [ -n "$push_SynoChat" ]; then
separator_line "="
content_line "是否确认关闭SynoChat日志推送"
separator_line "="
content_line "1) 是"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " res
if [ "$res" = 1 ]; then
push_SynoChat=
setconfig push_SynoChat
else
continue
fi
else
read -r -p "请输入你的Synology DSM主页地址> " URL
line_break
read -r -p "请输入你的Synology Chat Token> " TOKEN
line_break
separator_line "="
content_line '请通过"你的群晖地址/webapi/entry.cgi?api=SYNO.Chat.External&method=user_list&version=2&token=你的TOKEN"获取user_id'
separator_line "="
read -r -p "请输入你的user_id> " USERID
if [ -n "$URL" ]; then
push_SynoChat=$USERID
setconfig push_SynoChat "$USERID"
setconfig push_ChatURL "$URL"
setconfig push_ChatTOKEN "$TOKEN"
setconfig push_ChatUSERID "$USERID"
logger "已完成SynoChat日志推送设置" 32
else
setconfig push_ChatURL
setconfig push_ChatTOKEN
setconfig push_ChatUSERID
push_SynoChat=
setconfig push_SynoChat
line_break
separator_line "="
content_line "\033[31m输入错误请重新输入\033[0m"
separator_line "="
fi
sleep 1
fi
;;
# 在menu.sh的case $num in代码块中添加
7)
line_break
separator_line "="
if [ -n "$push_Gotify" ]; then
content_line "是否确认关闭Gotify日志推送"
separator_line "="
content_line "1) 是"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "请输入对应标号> " res
if [ "$res" = 1 ]; then
push_Gotify=
setconfig push_Gotify
else
continue
fi
else
content_line "请先通过Gotify服务器获取推送URL"
content_line "格式示例: https://gotify.example.com/message?token=你的应用令牌"
content_line ""
content_line "请直接你的Gotify推送URL"
content_line "或输入 0 返回上级菜单"
separator_line "="
read -r -p "请输入> " url
if [ "$url" = 0 ]; then
continue
elif [ -n "$url" ]; then
push_Gotify=$url
setconfig push_Gotify "$url"
logger "已完成Gotify日志推送设置" 32
else
line_break
separator_line "="
content_line "\033[31m输入错误请重新输入\033[0m"
separator_line "="
fi
sleep 1
fi
;;
a)
line_break
if [ -s "$TMPDIR"/ShellCrash.log ]; then
cat "$TMPDIR"/ShellCrash.log
else
separator_line "="
content_line "\033[31m未找到相关日志\033[0m"
separator_line "="
fi
sleep 1
;;
b)
[ "$task_push" = 1 ] && task_push='' || task_push=1
setconfig task_push "$task_push"
sleep 1
;;
c)
line_break
separator_line "="
content_line "请直接输入本设备自定义推送名称"
content_line "或直接回车确认返回上级菜单"
separator_line "="
read -r -p "请输入> " device_name
if [ -n "$device_name" ]; then
setconfig device_name "$device_name"
fi
;;
d)
rm -rf "$TMPDIR"/ShellCrash.log
line_break
separator_line "="
content_line "\033[33m运行日志及任务日志均已清空\033[0m"
separator_line "="
sleep 1
;;
*)
errornum
sleep 1
;;
esac
done
}
# 测试菜单
testcommand() {
while true; do
line_break
separator_line "="
content_line "\033[30;47m这里是测试命令菜单\033[0m"
content_line "\033[33m如遇问题尽量运行相应命令后截图提交issue或TG讨论组\033[0m"
separator_line "="
content_line "1) Debug模式运行内核"
content_line "2) 查看系统DNS端口(:53)占用 "
content_line "3) 测试ssl加密(aes-128-gcm)跑分"
content_line "4) 查看ShellCrash相关路由规则"
content_line "5) 查看内核配置文件前40行"
content_line "6) 测试代理服务器连通性(google.tw)"
content_line ""
content_line "0) 返回上级目录"
separator_line "="
read -r -p "请输入对应数字> " num
case "$num" in
0)
break
;;
1)
debug
testcommand
;;
2)
line_break
netstat -ntulp | grep 53
separator_line "="
content_line "可以使用\033[44m netstat -ntulp |grep xxx \033[0m来查询任意(xxx)端口"
separator_line "="
line_break
;;
3)
line_break
openssl speed -multi 4 -evp aes-128-gcm
line_break
;;
4)
line_break
if [ "$firewall_mod" = "nftables" ]; then
nft list table inet shellcrash | sed '/set cn_ip {/,/}/d;/set cn_ip6 {/,/}/d;/^[[:space:]]*}/d'
else
[ "$firewall_area" = 1 -o "$firewall_area" = 3 -o "$firewall_area" = 5 -o "$vm_redir" = "ON" ] && {
echo "----------------Redir+DNS---------------------"
iptables -t nat -L PREROUTING --line-numbers
iptables -t nat -L shellcrash_dns --line-numbers
[ -n "$(echo $redir_mod | grep -E 'Redir|Mix')" ] && iptables -t nat -L shellcrash --line-numbers
[ -n "$(echo "$redir_mod" | grep -E 'Tproxy|Mix|Tun')" ] && {
echo "----------------Tun/Tproxy-------------------"
iptables -t mangle -L PREROUTING --line-numbers
iptables -t mangle -L shellcrash_mark --line-numbers
}
}
[ "$firewall_area" = 2 -o "$firewall_area" = 3 ] && {
echo "-------------OUTPUT-Redir+DNS----------------"
iptables -t nat -L OUTPUT --line-numbers
iptables -t nat -L shellcrash_dns_out --line-numbers
[ -n "$(echo "$redir_mod" | grep -E 'Redir|Mix')" ] && iptables -t nat -L shellcrash_out --line-numbers
[ -n "$(echo "$redir_mod" | grep -E 'Tproxy|Mix|Tun')" ] && {
echo "------------OUTPUT-Tun/Tproxy---------------"
iptables -t mangle -L OUTPUT --line-numbers
iptables -t mangle -L shellcrash_mark_out --line-numbers
}
}
[ "$ipv6_redir" = "ON" ] && {
[ "$firewall_area" = 1 -o "$firewall_area" = 3 ] && {
ip6tables -t nat -L >/dev/null 2>&1 && {
echo "-------------IPV6-Redir+DNS-------------------"
ip6tables -t nat -L PREROUTING --line-numbers
ip6tables -t nat -L shellcrashv6_dns --line-numbers
[ -n "$(echo "$redir_mod" | grep -E 'Redir|Mix')" ] && ip6tables -t nat -L shellcrashv6 --line-numbers
}
[ -n "$(echo "$redir_mod" | grep -E 'Tproxy|Mix|Tun')" ] && {
echo "-------------IPV6-Tun/Tproxy------------------"
ip6tables -t mangle -L PREROUTING --line-numbers
ip6tables -t mangle -L shellcrashv6_mark --line-numbers
}
}
}
[ "$vm_redir" = "ON" ] && {
echo "-------------vm-Redir-------------------"
iptables -t nat -L shellcrash_vm --line-numbers
iptables -t nat -L shellcrash_vm_dns --line-numbers
}
echo "----------------本机防火墙---------------------"
iptables -L INPUT --line-numbers
fi
line_break
;;
5)
echo "$crashcore" | grep -q 'singbox' && config_path="$CRASHDIR"/jsons/config.json || config_path="$CRASHDIR"/yamls/config.yaml
line_break
sed -n '1,40p' "$config_path"
line_break
;;
6)
line_break
separator_line "="
content_line "\033[33m注意依赖curl不支持wget且测试结果不保证一定准确\033[0m"
separator_line "="
delay=$(
curl -kx ${authentication}@127.0.0.1:$mix_port -o /dev/null -s -w '%{time_starttransfer}' 'https://google.tw' &
{
sleep 3
kill $! >/dev/null 2>&1 &
}
) >/dev/null 2>&1
delay=$(echo | awk "{print $delay*1000}") >/dev/null 2>&1
line_break
separator_line "="
if [ $(echo ${#delay}) -gt 1 ]; then
content_line "\033[32m连接成功响应时间为"$delay" ms\033[0m"
else
content_line "\033[31m连接超时请重试或检查节点配置\033[0m"
fi
separator_line "="
;;
*)
errornum
;;
esac
done
}
debug() {
echo "$crashcore" | grep -q 'singbox' && config_tmp="$TMPDIR"/jsons || config_tmp="$TMPDIR"/config.yaml
line_break
separator_line "="
content_line "\033[36m注意Debug运行均会停止原本的内核服务\033[0m"
content_line "后台运行日志地址:\033[32m$TMPDIR/debug.log\033[0m"
content_line "如长时间运行后台监测日志等级推荐error防止文件过大"
content_line "你亦可通过:\033[33mcrash -s debug 'warning'\033[0m命令使用其他日志等级"
separator_line "="
content_line "1) 仅测试\033[32m$config_tmp\033[0m配置文件可用性"
content_line "2) 前台运行\033[32m$config_tmp\033[0m配置文件,不配置防火墙劫持(\033[33m使用Ctrl+C手动停止\033[0m)"
content_line "3) 后台运行完整启动流程,并配置防火墙劫持,日志等级:\033[31merror\033[0m"
content_line "4) 后台运行完整启动流程,并配置防火墙劫持,日志等级:\033[32minfo\033[0m"
content_line "5) 后台运行完整启动流程,并配置防火墙劫持,日志等级:\033[33mdebug\033[0m"
content_line "6) 后台运行完整启动流程,并配置防火墙劫持,且将错误日志打印到闪存:\033[32m$CRASHDIR/debug.log\033[0m"
content_line ""
content_line "8) 后台运行完整启动流程,输出执行错误并查找上下文,之后关闭进程"
[ -s "$TMPDIR"/jsons/inbounds.json ] && content_line " 9) 将\033[32m$config_tmp\033[0m下json文件合并为$TMPDIR/debug.json"
content_line ""
content_line "0) 返回上级目录"
separator_line "="
read -r -p "请输入对应标号> " num
case "$num" in
0) ;;
1)
"$CRASHDIR"/start.sh stop
"$CRASHDIR"/start.sh bfstart
if echo "$crashcore" | grep -q 'singbox'; then
"$TMPDIR"/CrashCore run -D "$BINDIR" -C "$TMPDIR"/jsons &
{
sleep 4
kill $! >/dev/null 2>&1 &
}
wait
else
"$TMPDIR"/CrashCore -t -d "$BINDIR" -f "$TMPDIR"/config.yaml
fi
rm -rf "$TMPDIR"/CrashCore
line_break
exit
;;
2)
"$CRASHDIR"/start.sh stop
"$CRASHDIR"/start.sh bfstart
$COMMAND
rm -rf "$TMPDIR"/CrashCore
line_break
exit
;;
3)
"$CRASHDIR"/start.sh debug error
main_menu
;;
4)
"$CRASHDIR"/start.sh debug info
main_menu
;;
5)
"$CRASHDIR"/start.sh debug debug
main_menu
;;
6)
line_break
separator_line "="
content_line "频繁写入闪存会导致闪存寿命降低如非遇到会导致设备死机或重启的bug请勿使用此功能"
separator_line "="
content_line "是否继续:"
separator_line "-"
content_line "1) 是"
content_line "0) 否"
separator_line "="
read -r -p "请输入对应标号> " res
if [ "$res" = 1 ]; then
"$CRASHDIR"/start.sh debug debug flash
fi
main_menu
;;
8)
$0 -d
main_menu
;;
9)
. "$CRASHDIR"/libs/core_webget.sh && core_find && "$TMPDIR"/CrashCore merge "$TMPDIR"/debug.json -C "$TMPDIR"/jsons && line_break
separator_line "="
content_line"\033[32m合并成功\033[0m"
separator_line "="
[ "$TMPDIR" = "$BINDIR" ] && rm -rf "$TMPDIR"/CrashCore
main_menu
;;
*)
errornum
;;
esac
}

1418
scripts/menus/9_upgrade.sh Normal file

File diff suppressed because it is too large Load Diff

3
scripts/menus/README.md Normal file
View File

@@ -0,0 +1,3 @@
用于存放脚本各级菜单界面的脚本
此处脚本内容包含各类文字说明

322
scripts/menus/bot_tg.sh Normal file
View File

@@ -0,0 +1,322 @@
#!/bin/sh
[ -z "$CRASHDIR" ] && CRASHDIR=$( cd $(dirname $0);cd ..;pwd)
. "$CRASHDIR"/libs/web_json.sh
. "$CRASHDIR"/libs/web_get_lite.sh
. "$CRASHDIR"/menus/running_status.sh
. "$CRASHDIR"/configs/gateway.cfg
. "$CRASHDIR"/configs/ShellCrash.cfg
TMPDIR='/tmp/ShellCrash'
API="https://api.telegram.org/bot$TG_TOKEN"
STATE_FILE="$TMPDIR/tgbot_state"
LOGFILE="$TMPDIR/tgbot.log"
OFFSET=0
### --- 基础函数 --- ###
web_download(){
setproxy
if curl --version >/dev/null 2>&1; then
curl -kfsSl "$1" -o "$2"
else
wget -Y on -q --timeout=3 -O "$2" "$1"
fi
}
web_upload(){
curl -ksSfl -X POST --connect-timeout 20 "$API/sendDocument" -F "chat_id=$TG_CHATID" -F "document=@$1" >/dev/null
}
send_msg(){
TEXT="$1"
web_json_post "$API/sendMessage" "{\"chat_id\":\"$TG_CHATID\",\"text\":\"$TEXT\",\"parse_mode\":\"Markdown\"}"
}
send_help(){
TEXT=$(cat <<EOF
进群讨论:
https://t.me/+6AElkMDzwPxmMmM1
项目地址:
https://github.com/juewuy/ShellClash
相关教程:
https://juewuy.github.io
请喝咖啡:
https://juewuy.github.io/yOF4Yf06Q/
友情机场:
https://dler.pro/auth/register?affid=89698
https://pub.bigmeok.me?code=2PuWY9I7
EOF
)
send_msg "$TEXT"
}
send_menu(){
#获取运行状态
PID=$(pidof CrashCore | awk '{print $NF}')
if [ -n "$PID" ]; then
run='🟢正在运行'
running_status
else
run='🟡未运行'
fi
corename=$(echo $crashcore | sed 's/singboxr/SingBoxR/' | sed 's/singbox/SingBox/' | sed 's/clash/Clash/' | sed 's/meta/Mihomo/')
TEXT=$(cat <<EOF
*欢迎使用ShellCrash*_${versionsh_l}_
$corename服务$run
【*$redir_mod*】内存占用:$VmRSS
已运行:$day$time
请选择操作:
EOF
)
MENU=$(cat <<EOF
{
"inline_keyboard":[
[
{"text":"✈️ 启用劫持","callback_data":"start_redir"},
{"text":"💧 纯净模式","callback_data":"stop_redir"},
{"text":"🕹 重启服务","callback_data":"restart"}
],
[
{"text":"📄 查看日志","callback_data":"readlog"},
{"text":"🔃 文件传输","callback_data":"transport"}
]
]
}
EOF
)
web_json_post "$API/sendMessage" "{\"chat_id\":\"$TG_CHATID\",\"text\":\"$TEXT\",\"parse_mode\":\"Markdown\",\"reply_markup\":$MENU}"
}
### --- 文件传输 --- ###
send_transport_menu(){
TEXT='请选择需要上传或下载的具体文件:'
if echo "$crashcore" | grep -q 'singbox';then
config_type=json
else
config_type=yaml
fi
if curl -h >/dev/null 2>&1;then
CURL_KB=$(cat <<EOF
[
{"text":"📥 下载日志","callback_data":"ts_get_log"},
{"text":"💾 备份设置","callback_data":"ts_get_bak"},
{"text":"⬇️ 下载配置","callback_data":"ts_get_ccf"}
],
EOF
)
else
CURL_KB='[{"text":"⚠️ 因当前设备缺少curl应用仅支持上传功能","callback_data":"noop"}],'
fi
MENU=$(cat <<EOF
{
"inline_keyboard":[
$CURL_KB
[
{"text":"🪐 上传内核","callback_data":"ts_up_core"},
{"text":"🔄 还原设置","callback_data":"ts_up_bak"},
{"text":"⬆️ 上传配置","callback_data":"ts_up_ccf"}
]
]
}
EOF
)
web_json_post "$API/sendMessage" "{\"chat_id\":\"$TG_CHATID\",\"text\":\"$TEXT\",\"parse_mode\":\"Markdown\",\"reply_markup\":$MENU}"
}
process_file(){
case "$FILE_TYPE" in
1)
. "$CRASHDIR"/libs/core_tools.sh
core_check "$TMPDIR/$FILE_NAME" && res='成功!即将重启服务!' || res='失败,请仔细检查文件或重试!'
send_msg "内核更新$res"
sleep 2
"$CRASHDIR"/start.sh start
;;
2)
tar -zxf "$TMPDIR/$FILE_NAME" -C "$CRASHDIR"/configs && res='配置文件已还原,请手动重启服务!' || res='解压还原失败,请仔细检查文件或重试!'
send_msg "$res"
;;
3)
mv -f "$TMPDIR/$FILE_NAME" "$CRASHDIR/${config_type}s/" && res='配置文件已上传,请手动重启服务!' || res='上传失败,请仔细检查文件或重试!'
send_msg "$res"
;;
esac
rm -f "$TMPDIR/$FILE_NAME"
send_menu
}
download_file(){
FILE_NAME=$(echo "$UPDATES" | sed 's/"callback_query".*//g' | grep -o '"file_name":"[^"]*"' | head -n1 | sed 's/.*:"//;s/"$//' | grep -E '\.(gz|upx|json|yaml)$')
if [ -n "$FILE_NAME" ];then
FILE_PATH=$(web_get_lite "$API/getFile?file_id=$FILE_ID" | grep -o '"file_path":"[^"]*"' | sed 's/.*:"//;s/"$//')
API_FILE="https://api.telegram.org/file/bot$TG_TOKEN"
web_download "$API_FILE/$FILE_PATH" "$TMPDIR/$FILE_NAME"
if [ "$?" = 0 ];then
process_file
else
send_msg "网络错误,上传失败!请重试!"
fi
else
send_msg "文件格式不匹配,上传失败!"
fi
}
### --- 具体操作函数 --- ###
do_start_fw(){
[ -z "$redir_mod_bf" ] && redir_mod_bf='Redir'
redir_mod=$redir_mod_bf
setconfig redir_mod $redir_mod
"$CRASHDIR"/start.sh start_firewall
echo "ShellCrash 透明路由*$redir_mod_bf*已启用!" > "$LOGFILE"
}
do_stop_fw(){
redir_mod_bf=$redir_mod
firewall_area=4
setconfig firewall_area 4
"$CRASHDIR"/start.sh stop_firewall
echo "ShellCrash 已切换到纯净模式!" > "$LOGFILE"
}
do_restart(){
"$CRASHDIR"/start.sh restart
echo "ShellCrash 服务已重启!" > "$LOGFILE"
}
do_set_sub(){
#echo "$1" "$2" >> "$CRASHDIR"/configs/providers.cfg
echo "错误,还未完成的功能!" > "$LOGFILE"
}
transport(){ #文件传输
case "$CALLBACK" in
"ts_get_log")
web_upload "$TMPDIR"/ShellCrash.log
send_menu
;;
"ts_get_bak")
now=$(date +%Y%m%d_%H%M%S)
FILE="$TMPDIR/configs_$now.tar.gz"
tar -zcf "$FILE" -C "$CRASHDIR/configs/" .
web_upload "$FILE"
rm -rf "$FILE"
send_menu
;;
"ts_get_ccf")
FILE="$TMPDIR/$config_type.tar.gz"
tar -zcf "$FILE" -C "$CRASHDIR/${config_type}s/" .
web_upload "$FILE"
rm -rf "$FILE"
send_menu
;;
"ts_up_core")
FILE_TYPE=1
send_msg "请发送需要上传的内核必须是以tar.gz,.gz或.upx结尾的【${corename}】内核!"
;;
"ts_up_bak")
FILE_TYPE=2
send_msg "请发送需要还原的备份文件,必须是【.tar.gz】格式"
;;
"ts_up_ccf")
FILE_TYPE=3
send_msg "请发送需要上传的配置文件,必须是【.${config_type}】格式,支持自定义配置文件"
;;
esac
}
### --- 轮询主进程 --- ###
polling(){
while true; do
UPDATES=$(web_get_lite "$API/getUpdates?timeout=25&offset=$OFFSET")
echo "$UPDATES" | grep -q '"update_id"' || {
sleep 10 #防止网络不佳时疯狂请求
continue
}
OFFSET=$(echo "$UPDATES" | grep -o '"update_id":[0-9]*' | tail -n1 | cut -d: -f2)
OFFSET=$((OFFSET + 1))
### --- 校验ChatID --- ###
CHATID=$(echo "$UPDATES" | grep -o '"id":[0-9]*' | tail -n1 | cut -d: -f2)
[ "$CHATID" != "$TG_CHATID" ] && continue
### --- 处理按钮事件 --- ###
CALLBACK=$(echo "$UPDATES" | grep -o '"data":"[^"]*"' | head -n1 | sed 's/.*:"//;s/"$//')
FILE_ID=$(echo "$UPDATES" | sed 's/"callback_query".*//g' | grep -o '"file_id":"[^"]*"' | head -n1 | sed 's/.*:"//;s/"$//')
[ -n "$FILE_ID" ] && {
download_file
continue
}
[ -n "$CALLBACK" ] && case "$CALLBACK" in
"start_redir")
if [ "$firewall_area" = 4 ];then
do_start_fw
send_msg "已切换到$redir_mod_bf"
else
send_msg "当前已经是$redir_mod"
fi
send_menu
continue
;;
"stop_redir")
if [ "$firewall_area" != 4 ];then
do_stop_fw
send_msg "已切换到纯净模式"
else
send_msg "当前已经是纯净模式!"
fi
send_menu
continue
;;
"restart")
do_restart
send_msg "🔄 服务已重启"
sleep 10
send_menu
continue
;;
"readlog")
send_msg "📄 日志内容如下(已过滤任务日志)\n\`\`\`$(grep -v '任务' $TMPDIR/ShellCrash.log |tail -n 20)\`\`\`"
sleep 3
send_menu
continue
;;
"transport")
send_transport_menu
continue
;;
"set_sub")
echo "await_sub" > "$STATE_FILE"
send_msg "✏ 请输入新的订阅链接:"
continue
;;
ts_*)
transport
continue
;;
esac
### --- 处理订阅输入 --- ###
TEXT=$(echo "$UPDATES" | grep -o '"text":"[^"]*"' | tail -n1 | sed 's/.*"text":"//;s/"$//')
if [ "$(cat "$STATE_FILE" 2>/dev/null)" = "await_sub" ]; then
echo "" > "$STATE_FILE"
do_set_sub "$TEXT"
send_msg "订阅更新完成:\n$(cat "$LOGFILE")"
send_menu
continue
fi
### 处理命令 ###
case "$TEXT" in
/crash)
send_menu
;;
/help)
send_help
;;
esac
done
}
#send_menu
polling

View File

@@ -0,0 +1,58 @@
#!/bin/sh
. "$CRASHDIR"/libs/web_get_lite.sh
private_bot() {
comp_box "请先通过 \033[32;4mhttps://t.me/BotFather\033[0m 申请TG机器人并获取其\033[36mAPI TOKEN\033[0m"
read -r -p "请输入你获取到的API TOKEN> " TOKEN
url_tg=https://api.telegram.org/bot${TOKEN}/getUpdates
top_box "请向\033[32m你申请的机器人\033[33m而不是BotFather\033[0m"
}
public_bot() {
comp_box "请向机器人:\033[32;4mhttps://t.me/ShellCrashtg_bot\033[0m"
TOKEN=publictoken
url_tg=https://tgbot.jwsc.eu.org/publictoken/getUpdates
}
tg_push_token() {
push_TG="$TOKEN"
setconfig push_TG "$TOKEN"
setconfig chat_ID "$chat_ID"
. "$CRASHDIR"/libs/logger.sh && logger "已完成Telegram日志推送设置" 32
}
get_chatid() {
i=1
chat_ID=''
while [ $i -le 3 ] && [ -z "$chat_ID" ]; do
sleep 1
comp_box "\033[33m第 $i 次尝试获取对话ID失败正在重试...\033[0m"
chat=$(web_get_lite "$url_tg" 2>/dev/null)
if [ -n "$chat" ]; then
chat_ID=$(echo "$chat" | sed 's/"update_id":/{\n"update_id":/g' | grep "$public_key" | head -n1 | grep -oE '"id":.*,"is_bot' | sed s'/"id"://' | sed s'/,"is_bot//')
fi
i=$((i + 1))
done
}
set_bot() {
public_key=$(cat /proc/sys/kernel/random/boot_id | sed 's/.*-//')
btm_box "发送此秘钥: \033[30;46m$public_key\033[0m"
read -r -p "我已经发送完成(1/0)> " res
if [ "$res" = 1 ]; then
get_chatid
[ -z "$chat_ID" ] && [ "$TOKEN" != 'publictoken' ] && {
comp_box "\033[31m无法获取对话ID请返回重新设置或手动输入ChatID\033[0m" \
"通常访问 \033[32;4m$url_tg\033[0m \n\033[36m即可看到ChatID\033[0m"
read -r -p "请手动输入ChatID> " chat_ID
}
if echo "$chat_ID" | grep -qE '^[0-9]{8,}$'; then
return 0
else
msg_alert "\033[31m无法获取对话ID请重新配置\033[0m"
return 1
fi
fi
}

View File

@@ -0,0 +1,18 @@
. "$CRASHDIR"/libs/set_cron.sh
bot_tg_start(){
bot_tg_stop
. "$CRASHDIR"/starts/start_legacy.sh
start_legacy "$CRASHDIR/menus/bot_tg.sh" 'bot_tg'
bot_tg_cron
}
bot_tg_stop(){
cronset 'TG_BOT守护进程'
[ -f "$TMPDIR/bot_tg.pid" ] && kill -TERM "$(cat "$TMPDIR/bot_tg.pid")"
killall bot_tg.sh 2>/dev/null
rm -f "$TMPDIR/bot_tg.pid"
}
bot_tg_cron(){
cronset 'TG_BOT守护进程' "* * * * * /bin/sh $CRASHDIR/starts/start_legacy_wd.sh bot_tg #ShellCrash-TG_BOT守护进程"
}

View File

@@ -0,0 +1,17 @@
#!/bin/sh
# Copyright (C) Juewuy
check_port() {
if [ "$1" -gt 65535 ] || [ "$1" -le 1 ]; then
msg_alert "\033[31m输入错误请输入正确的数值(1-65535)\033[0m"
return 1
elif echo "|$mix_port|$redir_port|$dns_port|$db_port|" | grep -q "|$1|"; then
msg_alert "\033[31m输入错误请不要输入重复的端口\033[0m"
return 1
elif netstat -ntul | grep -q ":$1[[:space:]]"; then
msg_alert "\033[31m当前端口已被其他进程占用请重新输入\033[0m"
return 1
else
return 0
fi
}

86
scripts/menus/common.sh Normal file
View File

@@ -0,0 +1,86 @@
msg_alert() {
# Default sleep time
_sleep_time=1
if [ "$1" = "-t" ] && [ -n "$2" ]; then
_sleep_time="$2"
shift 2
fi
line_break
separator_line "="
for line in "$@"; do
content_line "$line"
done
separator_line "="
sleep "$_sleep_time"
}
# complete box
comp_box() {
line_break
separator_line "="
for line in "$@"; do
content_line "$line"
done
separator_line "="
}
top_box() {
line_break
separator_line "="
for line in "$@"; do
content_line "$line"
done
}
# bottom box
btm_box() {
for line in "$@"; do
content_line "$line"
done
separator_line "="
}
list_box () {
i=1
printf '%s\n' "$1" | while IFS= read -r f; do
content_line "$i) $f$2"
i=$(( i + 1 ))
done
}
# =================================================
common_back() {
content_line "0) $COMMON_BACK"
separator_line "="
}
errornum() {
msg_alert "\033[31m$COMMON_ERR_NUM\033[0m"
}
error_letter() {
msg_alert "\033[31m$COMMON_ERR_LETTER\033[0m"
}
error_input() {
msg_alert "\033[31m$COMMON_ERR_INPUT\033[0m"
}
error_cancel() {
error_report "\033[31m$COMMON_ERR_CANCEL\033[0m"
}
cancel_back() {
separator_line "-"
content_line "$COMMON_CANCEL"
sleep 1
}
common_success() {
separator_line "-"
content_line "\033[32m$COMMON_SUCCESS\033[0m"
sleep 1
}

232
scripts/menus/ddns.sh Normal file
View File

@@ -0,0 +1,232 @@
#! /bin/bash
# Copyright (C) Juewuy
ddns_menu() {
top_box "\033[30;46m欢迎使用DDNS\033[0m"
load_ddns
}
add_ddns() {
cat >>"$ddns_dir" <<EOF
config service '$service'
option enabled '1'
option force_unit 'hours'
option lookup_host '$domain'
option service_name '$service_name'
option domain '$domain'
option username '$username'
option use_https '0'
option use_ipv6 '$use_ipv6'
option password '$password'
option ip_source 'web'
option check_unit 'minutes'
option check_interval '$check_interval'
option force_interval '$force_interval'
option interface 'wan'
option bind_network 'wan'
EOF
/usr/lib/ddns/dynamic_dns_updater.sh -S "$service" start >/dev/null 2>&1 &
sleep 3
msg_alert "服务已经添加!"
}
set_ddns() {
while true; do
line_break
read -r -p "请输入你的域名> " str
[ -z "$str" ] && domain="$domain" || domain="$str"
echo ""
read -r -p "请输入用户名或邮箱> " str
[ -z "$str" ] && username="$username" || username="$str"
echo ""
read -r -p "请输入密码或令牌秘钥> " str
[ -z "$str" ] && password="$password" || password="$str"
echo ""
read -r -p "请输入检测更新间隔(单位:分钟默认为10)> " check_interval
[ -z "$check_interval" ] || [ "$check_interval" -lt 1 -o "$check_interval" -gt 1440 ] && check_interval=10
echo ""
read -r -p "请输入强制更新间隔(单位:小时默认为24)> " force_interval
[ -z "$force_interval" ] || [ "$force_interval" -lt 1 -o "$force_interval" -gt 240 ] && force_interval=24
line_break
separator_line "="
content_line "请核对如下信息:"
content_line ""
content_line "服务商: \033[32m$service\033[0m"
content_line "域名: \033[32m$domain\033[0m"
content_line "用户名: \033[32m$username\033[0m"
content_line "检测间隔: \033[32m$check_interval\033[0m"
separator_line "="
content_line "是否确认添加:"
separator_line "="
content_line "1) 是"
content_line "0) 否,重新輸入"
separator_line "="
read -r -p "$COMMON_INPUT> " res
if [ "$res" = 1 ]; then
add_ddns
break
fi
done
}
set_ddns_service() {
while true; do
services_dir=/etc/ddns/"$serv"
[ -s "$services_dir" ] || services_dir=/usr/share/ddns/list
comp_box "\033[32m请选择服务提供商\033[0m"
# cat "$services_dir" | grep -v '^#' | awk '{print NR") " $1}'
awk '!/^#/ {print NR") " $1}' "$services_dir" |
while IFS= read -r line; do
content_line "$line"
done
nr=$(cat "$services_dir" | grep -v '^#' | wc -l)
common_back
read -r -p "请输入对应数字> " num
if [ -z "$num" ] || [ "$num" = 0 ]; then
i=
break
elif [ "$num" -gt 0 ] && [ "$num" -lt "$nr" ]; then
service_name=$(cat "$services_dir" | grep -v '^#' | awk '{print $1}' | sed -n "$num"p | sed 's/"//g')
service=$(echo "$service_name" | sed 's/\./_/g')
set_ddns
break
else
msg_alert "\033[33m输入错误请重新输入\033[0m"
fi
done
}
set_ddns_type() {
while true; do
comp_box "\033[32m请选择网络模式\033[0m"
content_line "1) \033[36mIPV4\033[0m"
content_line "2) \033[36mIPV6\033[0m"
content_line ""
common_back
read -r -p "请输入对应数字> " num
case "$num" in
"" | 0)
break
;;
1)
use_ipv6=0
serv=services
set_ddns_service
break
;;
2)
use_ipv6=1
serv=services_ipv6
set_ddns_service
break
;;
*)
msg_alert "\033[33m输入错误请重新输入\033[0m"
;;
esac
done
}
rev_ddns_service() {
while true; do
enabled=$(uci get ddns."$service".enabled)
[ "$enabled" = 1 ] && enabled_b="停用" || enabled_b="启用"
line_break
separator_line "="
content_line "1) \033[32m立即更新\033[0m"
content_line "2) 编辑当前服务"
content_line "3) $enabled_b当前服务"
content_line "4) 移除当前服务"
content_line "5) 查看运行日志"
content_line ""
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "请输入对应数字> " num
case "$num" in
"" | 0)
break
;;
1)
/usr/lib/ddns/dynamic_dns_updater.sh -S "$service" start >/dev/null 2>&1 &
sleep 3
break
;;
2)
domain=$(uci get ddns."$service".domain 2>/dev/null)
username=$(uci get ddns."$service".username 2>/dev/null)
password=$(uci get ddns."$service".password 2>/dev/null)
service_name=$(uci get ddns."$service".service_name 2>/dev/null)
uci delete ddns."$service"
set_ddns
break
;;
3)
[ "$enabled" = 1 ] && uci set ddns."$service".enabled='0' || uci set ddns."$service".enabled='1' && sleep 3
uci commit ddns."$service"
break
;;
4)
uci delete ddns."$service"
uci commit ddns."$service"
break
;;
5)
line_break
separator_line "="
cat /var/log/ddns/"$service".log 2>/dev/null
content_line ""
separator_line "="
sleep 1
break
;;
*)
msg_alert "\033[33m输入错误请重新输入\033[0m"
;;
esac
done
}
load_ddns() {
while true; do
ddns_dir=/etc/config/ddns
tmp_dir="$TMPDIR"/ddns
[ ! -f "$ddns_dir" ] && {
btm_box "\033[31m本脚本依赖OpenWrt内置的DDNS服务,当前设备无法运行,已退出!\033[0m"
sleep 1
return 1
}
nr=0
cat "$ddns_dir" | grep 'config service' | awk '{print $3}' | sed "s/'//g" | sed 's/"//g' >"$tmp_dir"
separator_line "="
content_line " 列表 域名 启用 IP地址"
content_line ""
[ -s "$tmp_dir" ] && for service in $(cat "$tmp_dir"); do
# echo $service >>$tmp_dir
nr=$((nr + 1))
enabled=$(uci get ddns."$service".enabled 2>/dev/null)
domain=$(uci get ddns."$service".domain 2>/dev/null)
local_ip=$(sed '1!G;h;$!d' /var/log/ddns/"$service".log 2>/dev/null | grep -E 'Registered IP' | tail -1 | awk -F "'" '{print $2}' | tr -d "'\"")
content_line "$nr) $domain $enabled $local_ip"
done
content_line "$((nr + 1))) 添加DDNS服务"
content_line "0) 退出"
separator_line "="
read -r -p "请输入对应序号> " num
if [ -z "$num" ] || [ "$num" = 0 ]; then
i=
rm -rf "$tmp_dir"
break
elif [ "$num" -gt $nr ]; then
set_ddns_type
elif [ "$num" -gt 0 ] && [ "$num" -le $nr ]; then
service=$(cat "$tmp_dir" | sed -n "$num"p)
rev_ddns_service
else
msg_alert "\033[33m请输入正确数字\033[0m"
fi
done
}

492
scripts/menus/dns.sh Normal file
View File

@@ -0,0 +1,492 @@
#!/bin/sh
# Copyright (C) Juewuy
[ -n "$__IS_MODULE_DNS_LOADED" ] && return
__IS_MODULE_DNS_LOADED=1
load_lang dns
# DNS 模式设置
set_dns_mod() {
while true; do
[ -z "$hosts_opt" ] && hosts_opt=ON
[ -z "$dns_protect" ] && dns_protect=ON
[ -z "$ecs_subnet" ] && ecs_subnet=OFF
line_break
separator_line "="
content_line "$DNS_CURRENT_MODE\033[47;30m $dns_mod \033[0m"
content_line "\033[33m$DNS_RESTART_NOTICE\033[0m"
separator_line "="
content_line "1) 设为MIX$COMMON_MOD\t\033[32m$DNS_MODE_MIX_DESC\033[0m"
content_line "2) 设为Route$COMMON_MOD\t\033[32m$DNS_MODE_ROUTE_DESC\033[0m"
content_line "3) 设为Redir$COMMON_MOD\t\033[33m$DNS_MODE_REDIR_DESC\033[0m"
content_line ""
content_line "4) $DNS_MENU_PROTECT\t \033[36m$dns_protect\033[0m\t$DNS_PROTECT_DESC"
content_line "5) $DNS_MENU_HOSTS\t \033[36m$hosts_opt\033[0m\t$DNS_HOSTS_DESC"
content_line "6) $DNS_MENU_ECS\t \033[36m$ecs_subnet\033[0m\t$DNS_ECS_DESC"
content_line "7) $DNS_MENU_REDIR\033[36m$dns_redir_port\033[0m\t$DNS_REDIR_PORT_DESC"
[ "$dns_mod" = "mix" ] &&
content_line "8) \033[33m$DNS_FAKEIP_MENU\033[0m"
content_line "9) \033[36m$DNS_ADV_MENU\033[0m"
content_line ""
content_line "0) $COMMON_BACK"
separator_line "="
read -r -p "$COMMON_INPUT> " num
case "$num" in
"" | 0)
break
;;
1 | 2)
line_break
separator_line "="
if echo "$crashcore" | grep -q 'singbox' || [ "$crashcore" = meta ]; then
[ "$num" = 1 ] && dns_mod=mix || dns_mod=route
setconfig dns_mod "$dns_mod"
content_line "\033[36m$DNS_SET_OK$dns_mod\033[0m"
else
econtent_line "\033[31m$DNS_CORE_UNSUPPORTED\033[0m"
fi
separator_line "="
sleep 1
;;
3)
dns_mod=redir_host
setconfig dns_mod "$dns_mod"
line_break
separator_line "="
content_line "\033[36m$DNS_SET_OK$dns_mod\033[0m"
separator_line "="
;;
4)
while true; do
line_break
separator_line "="
if [ "$dns_protect" = ON ]; then
content_line "当前\033[33m已启用\033[0mDNS防泄漏是否确认禁用"
else
content_line "当前\033[33m已禁用\033[0mDNS防泄漏是否确认启用"
fi
separator_line "="
content_line "1) 是"
content_line "2) 重置为默认值"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "$COMMON_INPUT> " num
case "$num" in
0)
break
;;
1)
if [ "$dns_protect" = ON ]; then
dns_protect=OFF
else
dns_protect=ON
fi
;;
2)
dns_protect=ON
;;
*)
errornum
sleep 1
continue
;;
esac
setconfig dns_protect "$dns_protect"
line_break
separator_line "="
content_line "\033[32m操作成功\033[0m"
separator_line "="
sleep 1
done
;;
5)
while true; do
line_break
separator_line "="
if [ "$hosts_opt" = ON ]; then
content_line "当前\033[33m已启用\033[0mHosts优化是否确认禁用"
else
content_line "当前\033[33m已禁用\033[0mHosts优化是否确认启用"
fi
separator_line "="
content_line "1) 是"
content_line "2) 重置为默认值"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "$COMMON_INPUT> " num
case "$num" in
0)
break
;;
1)
if [ "$hosts_opt" = ON ]; then
hosts_opt=OFF
else
hosts_opt=ON
fi
;;
2)
hosts_opt=ON
;;
*)
errornum
sleep 1
continue
;;
esac
setconfig dns_protect "$hosts_opt"
line_break
separator_line "="
content_line "\033[32m操作成功\033[0m"
separator_line "="
sleep 1
done
;;
6)
while true; do
line_break
separator_line "="
if [ "$ecs_subnet" = ON ]; then
content_line "当前\033[33m已启用\033[0mHosts优化是否确认禁用"
else
content_line "当前\033[33m已禁用\033[0mHosts优化是否确认启用"
fi
separator_line "="
content_line "1) 是"
content_line "2) 重置为默认值"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "$COMMON_INPUT> " num
case "$num" in
0)
break
;;
1)
if [ "$ecs_subnet" = ON ]; then
ecs_subnet=OFF
else
ecs_subnet=ON
fi
;;
2)
ecs_subnet=OFF
;;
*)
errornum
sleep 1
continue
;;
esac
setconfig dns_protect "$ecs_subnet"
line_break
separator_line "="
content_line "\033[32m操作成功\033[0m"
separator_line "="
sleep 1
done
;;
7)
while true; do
line_break
separator_line "="
content_line "\033[31m$DNS_REDIR_WARN\033[0m"
content_line "\033[33m$DNS_REDIR_HINT 127.0.0.1:$dns_port\033[0m"
content_line ""
content_line "请直接输入旁路由IPV4地址"
content_line "或输入 r 重置DNS劫持端口"
content_line "或输入 0 返回上级菜单"
separator_line "="
read -r -p "请输入> " num
case "$num" in
0)
break
;;
r)
dns_redir_port="$dns_port"
setconfig dns_redir_port
line_break
separator_line "="
content_line "\033[32m操作成功\033[0m"
separator_line "="
sleep 1
break
;;
*)
if [ "$num" -ge 1 ] && [ "$num" -lt 65535 ]; then
line_break
separator_line "="
if ckcmd netstat && netstat -ntul | grep -q ":$num "; then
dns_redir_port="$num"
setconfig dns_redir_port "$dns_redir_port"
content_line "\033[32m操作成功\033[0m"
separator_line "="
sleep 1
break
else
content_line "\033[33m$DNS_REDIR_NO_SERVICE\033[0m"
separator_line "="
sleep 1
fi
else
errornum
sleep 1
fi
;;
esac
done
;;
8)
fake_ip_filter
;;
9)
set_dns_adv
;;
*)
errornum
sleep 1
;;
esac
done
}
fake_ip_filter() {
while true; do
line_break
separator_line "="
content_line "\033[32m$DNS_FAKEIP_DESC\033[0m"
content_line "\033[31m$DNS_FAKEIP_TIP\033[0m"
content_line "\033[36m$DNS_FAKEIP_EXAMPLE\033[0m"
separator_line "="
if [ -s "$CRASHDIR/configs/fake_ip_filter" ]; then
content_line "\033[33m$DNS_FAKEIP_EXIST\033[0m"
content_line ""
awk '{print NR") "$1}' "$CRASHDIR/configs/fake_ip_filter" |
while IFS= read -r line; do
content_line "$line"
done
else
content_line "\033[33m$DNS_FAKEIP_EMPTY\033[0m"
fi
content_line ""
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "$DNS_FAKEIP_EDIT> " input
case "$input" in
"" | 0)
break
;;
*)
line_break
separator_line "="
if [ "$input" -ge 1 ] 2>/dev/null; then
if sed -i "${input}d" "$CRASHDIR/configs/fake_ip_filter"; then
content_line "\033[32m移除成功\033[0m"
else
content_line "\033[31m移除失败\033[0m"
fi
else
content_line "请确认需要添加的地址:\033[32m$input\033[0m"
separator_line "="
content_line "1) 确认无误"
content_line "0) 返回上级菜单"
separator_line "="
read -r -p "$COMMON_INPUT>" res
if [ "$res" = 1 ]; then
line_break
separator_line "="
if echo "$input" >>"$CRASHDIR/configs/fake_ip_filter"; then
content_line "\033[32m添加成功\033[0m"
else
content_line "\033[31m添加失败\033[0m"
fi
else
break
fi
fi
separator_line "="
sleep 1
;;
esac
done
}
# DNS详细设置
set_dns_adv() {
while true; do
line_break
separator_line "="
content_line "\033[31m$DNS_ADV_SINGBOX_LIMIT\033[0m"
content_line "$DNS_ADV_SPLIT"
content_line "\033[33m$DNS_ADV_CERT\033[0m"
content_line ""
content_line "DIRECT-DNS"
content_line "\033[32m$dns_nameserver\033[0m"
content_line ""
content_line "PROXY-DNS"
content_line "\033[36m$dns_fallback\033[0m"
content_line ""
content_line "DEFAULT-DNS"
content_line "\033[33m$dns_resolver\033[0m"
content_line ""
separator_line "="
content_line "1) $DNS_ADV_EDIT_DIRECT"
content_line "2) $DNS_ADV_EDIT_PROXY"
content_line "3) $DNS_ADV_EDIT_DEFAULT"
content_line "4) \033[32m$DNS_ADV_AUTO_ENCRYPT\033[0m"
content_line "9) \033[33m$DNS_ADV_RESET\033[0m"
content_line "0) $COMMON_BACK"
separator_line "="
read -r -p "$COMMON_INPUT > " num
case "$num" in
"" | 0)
break
;;
1)
line_break
separator_line "="
content_line "当前DIRECT-DNS\033[32m$dns_nameserver\033[0m"
separator_line "="
content_line "请直接输入新的DIRECT-DNS地址"
content_line "或输入 r 重置DIRECT-DNS地址"
content_line "或输入 0 返回上级菜单"
separator_line "="
read -r -p "请输入> " res
case "$res" in
0)
continue
;;
r)
dns_nameserver="127.0.0.1"
setconfig dns_nameserver "'$dns_nameserver'"
line_break
separator_line "="
content_line "\033[32m操作成功\033[0m"
;;
*)
dns_nameserver=$(echo "$res" | sed 's#|#,\ #g')
line_break
separator_line "="
if [ -n "$dns_nameserver" ]; then
setconfig dns_nameserver "'$dns_nameserver'"
content_line "\033[32m操作成功\033[0m"
else
ontent_line "\033[32m操作失败\033[0m"
fi
;;
esac
separator_line "="
;;
2)
line_break
separator_line "="
content_line "当前PROXY-DNS\033[32m$dns_fallback\033[0m"
separator_line "="
content_line "请直接输入新的PROXY-DNS地址"
content_line "或输入 r 重置PROXY-DNS地址"
content_line "或输入 0 返回上级菜单"
separator_line "="
read -r -p "请输入> " res
case "$res" in
0)
continue
;;
r)
dns_fallback="1.1.1.1, 8.8.8.8"
setconfig dns_fallback "'$dns_fallback'"
line_break
separator_line "="
content_line "\033[32m操作成功\033[0m"
;;
*)
dns_fallback=$(echo "$res" | sed 's#|#,\ #g')
line_break
separator_line "="
if [ -n "$dns_fallback" ]; then
setconfig dns_fallback "'$dns_fallback'"
content_line "\033[32m操作成功\033[0m"
else
ontent_line "\033[32m操作失败\033[0m"
fi
;;
esac
separator_line "="
;;
3)
line_break
separator_line "="
content_line "当前DEFAULT-DNS\033[32m$dns_resolver\033[0m"
separator_line "="
content_line "请直接输入新的DEFAULT-DNS地址"
content_line "或输入 r 重置DEFAULT-DNS地址"
content_line "或输入 0 返回上级菜单"
separator_line "="
read -r -p "请输入> " res
case "$res" in
0)
continue
;;
"r")
dns_resolver="223.5.5.5, 2400:3200::1"
setconfig dns_resolver "'$dns_resolver'"
line_break
separator_line "="
content_line "\033[32m操作成功\033[0m"
;;
*)
line_break
separator_line "="
if echo "$res" | grep -qE '://.*::'; then
content_line "\033[31m$DNS_IPV6_NOT_SUPPORT\033[0m"
else
dns_resolver=$(echo "$res" | sed 's#|#,\ #g')
setconfig dns_resolver "'$dns_resolver'"
content_line "\033[32m$COMMON_SUCCESS\033[0m"
fi
;;
esac
separator_line "="
;;
4)
line_break
separator_line "="
if echo "$crashcore" | grep -qE 'meta|singbox'; then
dns_nameserver='https://dns.alidns.com/dns-query, https://doh.pub/dns-query'
dns_fallback='https://cloudflare-dns.com/dns-query, https://dns.google/dns-query, https://doh.opendns.com/dns-query'
dns_resolver='https://223.5.5.5/dns-query, 2400:3200::1'
setconfig dns_nameserver "'$dns_nameserver'"
setconfig dns_fallback "'$dns_fallback'"
setconfig dns_resolver "'$dns_resolver'"
content_line "\033[32m$DNS_ENCRYPT_OK\033[0m"
else
content_line "\033[31m$DNS_CORE_REQUIRE\033[0m"
fi
separator_line "="
;;
9)
setconfig dns_nameserver
setconfig dns_fallback
setconfig dns_resolver
. "$CRASHDIR/libs/get_config.sh"
line_break
separator_line "="
content_line "\033[32m$COMMON_SUCCESS\033[0m"
separator_line "="
;;
*)
errornum
;;
esac
sleep 1
done
}

492
scripts/menus/fw_filter.sh Normal file
View File

@@ -0,0 +1,492 @@
#!/bin/sh
# Copyright (C) Juewuy
[ -n "$__IS_MODULE_FW_FILTER_LOADED" ] && return
__IS_MODULE_FW_FILTER_LOADED=1
# 流量过滤
set_fw_filter() {
while true; do
[ -z "$common_ports" ] && common_ports=ON
[ -z "$quic_rj" ] && quic_rj=OFF
[ -z "$cn_ip_route" ] && cn_ip_route=OFF
touch "$CRASHDIR"/configs/mac "$CRASHDIR"/configs/ip_filter
[ -z "$(cat "$CRASHDIR"/configs/mac "$CRASHDIR"/configs/ip_filter 2>/dev/null)" ] && mac_return=OFF || mac_return=ON
line_break
separator_line "="
content_line "1) 过滤非常用端口: \033[36m$common_ports\033[0m ———用于过滤P2P流量"
content_line "2) 过滤局域网设备: \033[36m$mac_return\033[0m ———使用黑/白名单进行过滤"
content_line "3) 过滤QUIC协议 \033[36m$quic_rj\033[0m ———优化视频性能"
content_line "4) 过滤CN_IP(4/6)列表:\033[36m$cn_ip_route\033[0m ———优化性能"
content_line "5) 自定义透明路由ipv4网段适合vlan等复杂网络环境"
content_line "6) 自定义保留地址ipv4网段需要以保留地址为访问目标的环境"
content_line ""
common_back
read -r -p "$COMMON_INPUT> " num
case "$num" in
"" | 0)
break
;;
1)
if [ -n "$(pidof CrashCore)" ] && [ "$firewall_mod" = 'iptables' ]; then
comp_box "切换时将停止服务,是否继续:"
content_line "1) 是"
content_line "0) 否,返回上级菜单"
separator_line "="
read -r -p "$COMMON_INPUT> " res
[ "$res" = 1 ] && "$CRASHDIR"/start.sh stop && set_common_ports
else
set_common_ports
fi
;;
2)
checkcfg_mac=$(cat "$CRASHDIR"/configs/mac)
fw_filter_lan
if [ -n "$PID" ]; then
checkcfg_mac_new=$(cat "$CRASHDIR"/configs/mac)
[ "$checkcfg_mac" != "$checkcfg_mac_new" ] && checkrestart
fi
;;
3)
if [ "$quic_rj" = "OFF" ]; then
quic_rj=ON
msg_alert "\033[33m已禁止QUIC流量通过ShellCrash内核\033[0m"
else
quic_rj=OFF
msg_alert "\033[33m已取消禁止QUIC协议流量\033[0m"
fi
setconfig quic_rj $quic_rj
;;
4)
if [ -n "$(ipset -v 2>/dev/null)" ] || [ "$firewall_mod" = 'nftables' ]; then
if [ "$cn_ip_route" = "OFF" ]; then
cn_ip_route=ON
msg_alert -t 2 "\033[32m已开启CN_IP绕过内核功能\033[0m" \
"\033[31m注意此功能会导致全局模式及一切CN相关规则失效\033[0m"
else
cn_ip_route=OFF
msg_alert "\033[33m已禁用CN_IP绕过内核功能\033[0m"
fi
setconfig cn_ip_route $cn_ip_route
else
msg_alert "\033[31m当前设备缺少ipset模块或未使用nftables模式无法启用绕过功能\033[0m"
fi
;;
5)
set_cust_host_ipv4
;;
6)
while true; do
[ -z "$reserve_ipv4" ] && reserve_ipv4="0.0.0.0/8 10.0.0.0/8 127.0.0.0/8 100.64.0.0/10 169.254.0.0/16 172.16.0.0/12 192.168.0.0/16 224.0.0.0/4 240.0.0.0/4"
comp_box "\033[33m注意地址必须是空格分隔错误的设置可能导致网络回环或启动报错请务必谨慎\033[0m" \
"" \
"当前网段:" \
"\033[36m$reserve_ipv4\033[0m"
btm_box "请直接输入自定义保留地址ipv4网段" \
"或输入 0 返回上级菜单"
read -r -p "请输入> " text
if [ "$text" = 0 ]; then
break
elif
echo "$text" | grep -Eq "(((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])/(3[0-2]|[1-2]?[0-9]))( +|$)+"
then
reserve_ipv4="$text"
if setconfig reserve_ipv4 "'$reserve_ipv4'"; then
msg_alert "已将保留地址网段设为:\033[32m$reserve_ipv4\033[0m"
else
msg_alert "\033[31m$COMMON_FAILED\033[0m"
fi
else
msg_alert "\033[31m输入有误请重新输入\033[0m"
fi
done
;;
*)
errornum
;;
esac
done
}
set_common_ports() {
while true; do
[ -z "$multiport" ] && multiport='22,80,443,8080,8443'
line_break
separator_line "="
content_line "\033[31m注意\n\033[0mMIX模式下所有fake-ip来源的非常用端口流量不会被过滤"
if [ -n "$common_ports" ]; then
content_line ""
content_line "当前已放行端口:\033[36m$multiport\033[0m"
fi
separator_line "="
content_line "1) 启用/关闭端口过滤: \033[36m$common_ports\033[0m"
content_line "2) 添加放行端口"
content_line "3) 移除指定放行端口"
content_line "4) 重置默认放行端口"
content_line "5) 重置为旧版放行端口"
content_line ""
common_back
read -r -p "$COMMON_INPUT> " num
case "$num" in
"" | 0)
break
;;
1)
if [ "$common_ports" = ON ]; then
common_ports=OFF
else
common_ports=ON
fi
if setconfig common_ports "$common_ports"; then
msg_alert "\033[32m$COMMON_SUCCESS\033[0m"
else
msg_alert "\033[31m$COMMON_FAILED\033[0m"
fi
;;
2)
while true; do
port_count=$(echo "$multiport" | awk -F',' '{print NF}')
if [ "$port_count" -ge 15 ]; then
comp_box "\033[31m最多支持设置放行15个端口请先减少一些\033[0m"
else
comp_box "当前已放行端口:\033[36m$multiport\033[0m"
btm_box "请直接输入要放行的端口号\n每次只能输入一个端口号切勿一次添加多个端口号" \
"或输入 0 返回上级菜单"
read -r -p "请输入> " port
if [ "$port" = 0 ]; then
break
elif echo ",$multiport," | grep -q ",$port,"; then
msg_alert "\033[31m输入错误请勿重复添加\033[0m"
elif [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
msg_alert "\033[31m输入错误请输入正确的数值165535\033[0m"
else
multiport=$(echo "$multiport,$port" | sed "s/^,//")
if setconfig multiport "$multiport"; then
msg_alert "\033[32m$COMMON_SUCCESS\033[0m"
else
msg_alert "\033[31m$COMMON_FAILED\033[0m"
fi
fi
fi
done
;;
3)
while true; do
comp_box "当前已放行端口:\033[36m$multiport\033[0m"
btm_box "请直接输入要移除的端口号\n每次只能输入一个端口号切勿一次添加多个端口号" \
"或输入 0 返回上级菜单"
read -r -p "请输入> " port
if [ "$port" = 0 ]; then
break
elif echo ",$multiport," | grep -q ",$port,"; then
if [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
msg_alert "\033[31m输入错误请输入正确的数值165535\033[0m"
else
multiport=$(echo ",$multiport," | sed "s/,$port//; s/^,//; s/,$//")
if setconfig multiport "$multiport"; then
msg_alert "\033[32m$COMMON_SUCCESS\033[0m"
else
msg_alert "\033[31m$COMMON_FAILED\033[0m"
fi
fi
else
msg_alert "\033[31m输入错误请输入已添加过的端口\033[0m"
fi
done
;;
4)
multiport=''
if setconfig multiport; then
msg_alert "\033[32m$COMMON_SUCCESS\033[0m"
else
msg_alert "\033[31m$COMMON_FAILED\033[0m"
fi
;;
5)
multiport='22,80,143,194,443,465,587,853,993,995,5222,8080,8443'
if setconfig multiport "$multiport"; then
msg_alert "\033[32m$COMMON_SUCCESS\033[0m"
else
msg_alert "\033[31m$COMMON_FAILED\033[0m"
fi
;;
*)
errornum
;;
esac
done
}
# 自定义ipv4透明路由网段
set_cust_host_ipv4() {
while true; do
[ -z "$replace_default_host_ipv4" ] && replace_default_host_ipv4="OFF"
. "$CRASHDIR"/starts/fw_getlanip.sh && getlanip
comp_box "当前默认透明路由的网段为:\033[32m$host_ipv4\033[0m" \
"当前已添加的自定义网段为:\033[36m$cust_host_ipv4\033[0m"
content_line "1) 移除所有自定义网段"
content_line "2) 使用自定义网段覆盖默认网段 \033[36m$replace_default_host_ipv4\033[0m"
common_back
read -r -p "请输入对应的序号或需要额外添加的网段> " text
case "$text" in
"" | 0)
break
;;
1)
unset cust_host_ipv4
if setconfig cust_host_ipv4; then
msg_alert "\033[32m$COMMON_SUCCESS\033[0m"
else
msg_alert "\033[31m$COMMON_FAILED\033[0m"
fi
;;
2)
if [ "$replace_default_host_ipv4" = "OFF" ]; then
replace_default_host_ipv4="ON"
else
replace_default_host_ipv4="OFF"
fi
if setconfig replace_default_host_ipv4 "$replace_default_host_ipv4"; then
msg_alert "\033[32m$COMMON_SUCCESS\033[0m"
else
msg_alert "\033[31m$COMMON_FAILED\033[0m"
fi
;;
*)
if [ -n "$(echo "$text" | grep -Eo '^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]{1,2}'$)" ] && echo "$cust_host_ipv4" | grep -q "$text"; then
cust_host_ipv4="$cust_host_ipv4 $text"
if setconfig cust_host_ipv4 "'$cust_host_ipv4'"; then
msg_alert "\033[32m$COMMON_SUCCESS\033[0m"
else
msg_alert "\033[31m$COMMON_FAILED\033[0m"
fi
else
msg_alert "\033[31m请输入正确的网段地址\033[0m"
fi
;;
esac
done
}
# 局域网设备过滤
fw_filter_lan() {
get_devinfo() {
dev_ip=$(cat "$dhcpdir" | grep " $dev " | awk '{print $3}') && [ -z "$dev_ip" ] && dev_ip=$dev
dev_mac=$(cat "$dhcpdir" | grep " $dev " | awk '{print $2}') && [ -z "$dev_mac" ] && dev_mac=$dev
dev_name=$(cat "$dhcpdir" | grep " $dev " | awk '{print $4}') && [ -z "$dev_name" ] && dev_name='未知设备'
}
add_mac() {
while true; do
comp_box "手动输入mac地址时仅支持\033[32mxx:xx:xx:xx:xx:xx\033[0m的形式"
content_line "已添加的mac地址"
content_line ""
if [ -s "$CRASHDIR/configs/mac" ]; then
while IFS= read -r line; do
content_line "$line"
done <"$CRASHDIR/configs/mac"
else
content_line "暫未添加任何mac地址"
fi
separator_line "="
content_line "序号 \033[33m设备IP 设备mac地址 设备名称\033[0m"
if [ -s "$dhcpdir" ]; then
awk '{print NR") "$3,$2,$4}' "$dhcpdir" |
while IFS= read -r line; do
content_line "$line"
done
else
content_line "无纪录"
fi
content_line ""
common_back
read -r -p "请输入对应序号或直接输入mac地址> " num
if [ -z "$num" ] || [ "$num" = 0 ]; then
i=
break
elif echo "$num" | grep -aEq '^([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2})$'; then
if [ -z "$(cat "$CRASHDIR"/configs/mac | grep -E "$num")" ]; then
echo "$num" | grep -oE '^([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2})$' >>"$CRASHDIR"/configs/mac
else
msg_alert "\033[31m已添加的设备请勿重复添加\033[0m"
fi
elif [ "$num" -le $(cat $dhcpdir 2>/dev/null | awk 'END{print NR}') ]; then
macadd=$(cat "$dhcpdir" | awk '{print $2}' | sed -n "$num"p)
if [ -z "$(cat "$CRASHDIR"/configs/mac | grep -E "$macadd")" ]; then
echo "$macadd" >>"$CRASHDIR"/configs/mac
else
msg_alert "\033[31m已添加的设备请勿重复添加\033[0m"
fi
else
msg_alert "\033[31m输入有误请重新输入\033[0m"
fi
done
}
add_ip() {
while true; do
comp_box "手动输入时仅支持 \033[32m192.168.1.0/24\033[0m 或 \033[32m192.168.1.0\033[0m 的形式" \
"不支持ipv6地址过滤如有需求请使用mac地址过滤"
content_line "已添加的IP地址"
content_line ""
if [ -s "$CRASHDIR/configs/ip_filter" ]; then
while IFS= read -r line; do
content_line "$line"
done <"$CRASHDIR/configs/ip_filter"
else
content_line "暫未添加任何IP地址"
fi
separator_line "="
content_line "\033[33m序号 设备IP 设备名称\033[32m"
if [ -s "$dhcpdir" ]; then
awk '{print NR") "$3, $4}' "$dhcpdir" |
while IFS= read -r line; do
content_line "$line"
done
else
content_line "无纪录"
fi
content_line ""
common_back
read -r -p "请输入对应序号或直接输入IP地址段> " num
if [ -z "$num" ] || [ "$num" = 0 ]; then
i=
break
elif echo "$num" | grep -aEq '^((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]?)(/(3[0-2]|[12]?[0-9]))?$'; then
if [ -z "$(cat "$CRASHDIR"/configs/ip_filter | grep -E "$num")" ]; then
echo "$num" | grep -oE '^((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]?)(/(3[0-2]|[12]?[0-9]))?$' >>"$CRASHDIR"/configs/ip_filter
else
msg_alert "\033[31m已添加的地址请勿重复添加\033[0m"
fi
elif [ "$num" -le "$(cat "$dhcpdir" 2>/dev/null | awk 'END{print NR}')" ]; then
ipadd=$(cat "$dhcpdir" | awk '{print $3}' | sed -n "$num"p)
if [ -z "$(cat "$CRASHDIR"/configs/mac | grep -E "$ipadd")" ]; then
echo "$ipadd" >>"$CRASHDIR"/configs/ip_filter
else
msg_alert "\033[31m已添加的地址请勿重复添加\033[0m"
fi
else
msg_alert "\033[31m输入有误请重新输入\033[0m"
fi
done
}
del_all() {
while true; do
if [ -z "$(cat "$CRASHDIR"/configs/mac "$CRASHDIR"/configs/ip_filter 2>/dev/null)" ]; then
msg_alert "\033[31m列表中没有需要移除的设备\033[0m"
break
else
comp_box "请选择需要移除的设备:"
content_line " \033[32m设备IP \033[36m设备mac地址 \033[35m设备名称\033[0m"
i=1
for dev in $(cat "$CRASHDIR"/configs/mac "$CRASHDIR"/configs/ip_filter 2>/dev/null); do
get_devinfo
content_line "$(printf "%s) \033[32m%-18s \033[36m%-18s \033[35m%s\033[0m" \
"$i" "$dev_ip" "$dev_mac" "$dev_name")"
i=$((i + 1))
done
content_line ""
common_back
read -r -p "$COMMON_INPUT> " num
mac_filter_rows=$(cat "$CRASHDIR"/configs/mac 2>/dev/null | wc -l)
ip_filter_rows=$(cat "$CRASHDIR"/configs/ip_filter 2>/dev/null | wc -l)
if [ -z "$num" ] || [ "$num" -le 0 ]; then
n=
break
elif [ "$num" -le "$mac_filter_rows" ]; then
sed -i "${num}d" "$CRASHDIR"/configs/mac
msg_alert "\033[32m对应设备已移除\033[0m"
elif [ "$num" -le $((mac_filter_rows + ip_filter_rows)) ]; then
num=$((num - mac_filter_rows))
sed -i "${num}d" "$CRASHDIR"/configs/ip_filter
msg_alert "\033[32m对应设备已移除\033[0m"
else
msg_alert "\033[31m输入有误请重新输入\033[0m"
fi
fi
done
}
while true; do
[ -z "$dhcpdir" ] && [ -f /var/lib/dhcp/dhcpd.leases ] && dhcpdir='/var/lib/dhcp/dhcpd.leases'
[ -z "$dhcpdir" ] && [ -f /var/lib/dhcpd/dhcpd.leases ] && dhcpdir='/var/lib/dhcpd/dhcpd.leases'
[ -z "$dhcpdir" ] && [ -f /tmp/dhcp.leases ] && dhcpdir='/tmp/dhcp.leases'
[ -z "$dhcpdir" ] && [ -f /tmp/dnsmasq.leases ] && dhcpdir='/tmp/dnsmasq.leases'
[ -z "$dhcpdir" ] && dhcpdir='/dev/null'
[ -z "$macfilter_type" ] && macfilter_type='黑名单'
if [ "$macfilter_type" = "黑名单" ]; then
fw_filter_lan_over='白名单'
fw_filter_lan_scrip='不'
else
fw_filter_lan_over='黑名单'
fw_filter_lan_scrip=''
fi
comp_box "\033[30;47m请在此添加或移除设备\033[0m" \
"" \
"当前过滤方式为:\033[33m$fw_filter_lan_type模式\033[0m" \
"仅列表内设备流量\033[36m$fw_filter_lan_scrip经过\033[0m内核"
if [ -n "$(cat "$CRASHDIR"/configs/mac)" ]; then
content_line "当前已过滤设备为:"
content_line ""
content_line " \033[36m设备mac/ip地址\033[0m \033[35m设备名称\033[0m"
for dev in $(cat "$CRASHDIR"/configs/mac 2>/dev/null); do
get_devinfo
content_line "$(printf "\033[36m%-20s \033[35m%s\033[0m" \
"$dev_mac" "$dev_name")"
done
for dev in $(cat "$CRASHDIR"/configs/ip_filter 2>/dev/null); do
get_devinfo
content_line "$(printf "\033[36m%-20s \033[35m%s\033[0m" \
"$dev_ip" "$dev_name")"
done
separator_line "="
fi
content_line "1) 切换为\033[33m$fw_filter_lan_over模式\033[0m"
content_line "2) \033[32m添加指定设备mac地址\033[0m"
content_line "3) \033[32m添加指定设备IP地址网段\033[0m"
content_line "4) \033[36m移除指定设备\033[0m"
content_line "9) \033[31m清空整个列表\033[0m"
content_line ""
common_back
read -r -p "$COMMON_INPUT> " num
case "$num" in
"" | 0)
break
;;
1)
macfilter_type=$fw_filter_lan_over
if setconfig macfilter_type $macfilter_type; then
msg_alert "\033[32m已切换为$fw_filter_lan_type模式\033[0m"
else
msg_alert "\033[31m$COMMON_FAILED\033[0m"
fi
;;
2)
add_mac
;;
3)
add_ip
;;
4)
del_all
;;
9)
: >"$CRASHDIR"/configs/mac
: >"$CRASHDIR"/configs/ip_filter
msg_alert "\033[31m设备列表已清空\033[0m"
;;
*)
errornum
;;
esac
done
}

483
scripts/menus/override.sh Normal file
View File

@@ -0,0 +1,483 @@
#!/bin/sh
# Copyright (C) Juewuy
[ -n "$__IS_MODULE_OVERRIDE" ] && return
__IS_MODULE_OVERRIDE=1
# 配置文件覆写
override() {
while true; do
[ -z "$rule_link" ] && rule_link=1
[ -z "$server_link" ] && server_link=1
echo "-----------------------------------------------"
echo -e "\033[30;47m 欢迎使用配置文件覆写功能!\033[0m"
echo "-----------------------------------------------"
echo -e " 1 自定义\033[32m端口及秘钥\033[0m"
echo -e " 2 管理\033[36m自定义规则\033[0m"
echo "$crashcore" | grep -q 'singbox' || {
echo -e " 3 管理\033[33m自定义节点\033[0m"
echo -e " 4 管理\033[36m自定义策略组\033[0m"
}
echo -e " 5 \033[32m自定义\033[0m高级功能"
[ "$disoverride" != 1 ] && echo -e " 9 \033[33m禁用\033[0m配置文件覆写"
echo "-----------------------------------------------"
[ "$inuserguide" = 1 ] || echo -e " 0 返回上级菜单"
read -p "请输入对应数字 > " num
case "$num" in
"" | 0)
break
;;
1)
if [ -n "$(pidof CrashCore)" ]; then
echo "-----------------------------------------------"
echo -e "\033[33m检测到服务正在运行需要先停止服务\033[0m"
read -p "是否停止服务?(1/0) > " res
if [ "$res" = "1" ]; then
"$CRASHDIR"/start.sh stop
setport
fi
else
setport
fi
;;
2)
setrules
;;
3)
setproxies
;;
4)
setgroups
;;
5)
echo "$crashcore" | grep -q 'singbox' && set_singbox_adv || set_clash_adv
sleep 3
;;
9)
echo "-----------------------------------------------"
echo -e "\033[33m此功能可能会导致严重问题启用后脚本中大部分功能都将禁用\033[0m"
echo -e "如果你不是非常了解$crashcore的运行机制,切勿开启!\033[0m"
echo -e "\033[33m继续后如出现任何问题请务必自行解决一切提问恕不受理\033[0m"
echo "-----------------------------------------------"
sleep 2
read -p "我确认遇到问题可以自行解决[1/0] > " res
[ "$res" = '1' ] && {
disoverride=1
setconfig disoverride $disoverride
echo "-----------------------------------------------"
echo -e "\033[32m设置成功\033[0m"
}
;;
*)
errornum
sleep 1
break
;;
esac
done
}
setrules() { # 自定义规则
set_rule_type() {
echo "-----------------------------------------------"
echo -e "\033[33m请选择规则类型\033[0m"
echo "$rule_type" | awk -F ' ' '{for(i=1;i<=NF;i++){print i" "$i}}'
echo -e " 0 返回上级菜单"
read -p "请输入对应数字 > " num
case "$num" in
"" | 0) ;;
[0-9]*)
if [ "$num" -gt $(echo $rule_type | awk -F " " '{print NF}') ]; then
errornum
sleep 1
else
rule_type_set=$(echo "$rule_type" | cut -d' ' -f"$num")
echo "-----------------------------------------------"
echo -e "\033[33m请输入规则语句可以是域名、泛域名、IP网段或者其他匹配规则类型的内容\033[0m"
read -p "请输入对应规则 > " rule_state_set
if [ -n "$rule_state_set" ]; then
set_group_type
else
errornum
slepp 1
fi
fi
;;
*)
errornum
sleep 1
;;
esac
}
set_group_type() {
echo "-----------------------------------------------"
echo -e "\033[36m请选择具体规则\033[0m"
echo -e "\033[33m此处规则读取自现有配置文件如果你后续更换配置文件时运行出错请尝试重新添加\033[0m"
echo "$rule_group" | awk -F '#' '{for(i=1;i<=NF;i++){print i" "$i}}'
echo -e " 0 返回上级菜单"
read -p "请输入对应数字 > " num
case "$num" in
"" | 0) ;;
[0-9]*)
if [ "$num" -gt "$(echo "$rule_group" | awk -F "#" '{print NF}')" ]; then
errornum
sleep 1
else
rule_group_set=$(echo "$rule_group" | cut -d'#' -f"$num")
rule_all="- ${rule_type_set},${rule_state_set},${rule_group_set}"
echo "IP-CIDR SRC-IP-CIDR IP-CIDR6" | grep -q -- "$rule_type_set" && rule_all="${rule_all},no-resolve"
echo "$rule_all" >>"$YAMLSDIR"/rules.yaml
echo "-----------------------------------------------"
echo -e "\033[32m添加成功\033[0m"
fi
;;
*)
errornum
sleep 1
;;
esac
}
del_rule_type() {
while true; do
echo -e "输入对应数字即可移除相应规则:"
sed -i '/^ *$/d; /^#/d' "$YAMLSDIR"/rules.yaml
cat "$YAMLSDIR"/rules.yaml | grep -Ev '^#' | awk -F "#" '{print " "NR" "$1$2$3}'
echo "-----------------------------------------------"
echo -e " 0 返回上级菜单"
read -p "请输入对应数字 > " num
case "$num" in
"" | 0)
break
;;
*)
if [ "$num" -le "$(wc -l <"$YAMLSDIR"/rules.yaml)" ]; then
sed -i "${num}d" "$YAMLSDIR"/rules.yaml
sleep 1
else
errornum
sleep 1
break
fi
;;
esac
done
}
get_rule_group() {
. "$CRASHDIR"/libs/web_save.sh
get_save http://127.0.0.1:${db_port}/proxies | sed 's/:{/!/g' | awk -F '!' '{for(i=1;i<=NF;i++) print $i}' | grep -aE '"Selector|URLTest|LoadBalance"' | grep -aoE '"name":.*"now":".*",' | awk -F '"' '{print "#"$4}' | tr -d '\n'
}
while true; do
echo "-----------------------------------------------"
echo -e "\033[33m你可以在这里快捷管理自定义规则\033[0m"
echo -e "如需批量操作,请手动编辑:\033[36m $YAMLSDIR/rules.yaml\033[0m"
echo -e "\033[33msingbox和clash共用此处规则可无缝切换\033[0m"
echo -e "大量规则请尽量使用rule-set功能添加\033[31m此处过量添加可能导致启动卡顿\033[0m"
echo "-----------------------------------------------"
echo -e " 1 新增自定义规则"
echo -e " 2 移除自定义规则"
echo -e " 3 清空规则列表"
echo "$crashcore" | grep -q 'singbox' || echo -e " 4 配置节点绕过: \033[36m$proxies_bypass\033[0m"
echo -e " 0 返回上级菜单"
read -p "请输入对应数字 > " num
case "$num" in
"" | 0)
break
;;
1)
rule_type="DOMAIN-SUFFIX DOMAIN-KEYWORD IP-CIDR SRC-IP-CIDR DST-PORT SRC-PORT GEOIP GEOSITE IP-CIDR6 DOMAIN PROCESS-NAME"
rule_group="DIRECT#REJECT$(get_rule_group)"
set_rule_type
;;
2)
echo "-----------------------------------------------"
if [ -s "$YAMLSDIR"/rules.yaml ]; then
del_rule_type
else
echo -e "请先添加自定义规则!"
sleep 1
fi
;;
3)
read -p "确认清空全部自定义规则?(1/0) > " res
[ "$res" = "1" ] && sed -i '/^\s*[^#]/d' "$YAMLSDIR"/rules.yaml
;;
4)
echo "-----------------------------------------------"
if [ "$proxies_bypass" = "OFF" ]; then
echo -e "\033[33m本功能会自动将当前配置文件中的节点域名或IP设置为直连规则以防止出现双重流量\033[0m"
echo -e "\033[33m请确保下游设备使用的节点与ShellCrash中使用的节点相同否则无法生效\033[0m"
read -p "启用节点绕过?(1/0) > " res
[ "$res" = "1" ] && proxies_bypass=ON
else
proxies_bypass=OFF
fi
setconfig proxies_bypass "$proxies_bypass"
sleep 1
;;
*)
errornum
sleep 1
;;
esac
done
}
setgroups() { # 自定义clash策略组
set_group_type() {
echo "-----------------------------------------------"
echo -e "\033[33m注意策略组名称必须和【自定义规则】或【自定义节点】功能中指定的策略组一致\033[0m"
echo -e "\033[33m建议先创建策略组之后可在【自定义规则】或【自定义节点】功能中智能指定\033[0m"
echo -e "\033[33m如需在当前策略组下添加节点请手动编辑$YAMLSDIR/proxy-groups.yaml\033[0m"
read -r -p "请输入自定义策略组名称(不支持纯数字且不要包含特殊字符!) > " new_group_name
echo "-----------------------------------------------"
echo -e "\033[32m请选择策略组【$new_group_name】的类型!\033[0m"
echo "$group_type_cn" | awk '{for(i=1;i<=NF;i++){print i" "$i}}'
read -r -p "请输入对应数字 > " num
new_group_type=$(echo "$group_type" | awk '{print $'"$num"'}')
if [ "$num" = "1" ]; then
unset new_group_url interval
else
read -r -p "请输入测速地址回车则默认使用https://www.gstatic.com/generate_204 > " new_group_url
[ -z "$new_group_url" ] && new_group_url=https://www.gstatic.com/generate_204
new_group_url="url: '$new_group_url'"
interval="interval: 300"
fi
set_group_add
# 添加自定义策略组
cat >>"$YAMLSDIR"/proxy-groups.yaml <<EOF
- name: $new_group_name
type: $new_group_type
$new_group_url
$interval
proxies:
- DIRECT
EOF
sed -i "/^ *$/d" "$YAMLSDIR"/proxy-groups.yaml
echo "-----------------------------------------------"
echo -e "\033[32m添加成功\033[0m"
}
set_group_add() {
echo "-----------------------------------------------"
echo -e "\033[36m请选择想要将本策略添加到的策略组\033[0m"
echo -e "\033[32m如需添加到多个策略组请一次性输入多个数字并用空格隔开\033[0m"
echo "-----------------------------------------------"
echo "$proxy_group" | awk -F '#' '{for(i=1;i<=NF;i++){print i" "$i}}'
echo "-----------------------------------------------"
echo -e " 0 跳过添加"
read -r -p "请输入对应数字(多个用空格隔开) > " char
case "$char" in
"" | 0) ;;
*)
for num in $char; do
rule_group_set=$(echo "$proxy_group" | cut -d'#' -f"$num")
rule_group_add="${rule_group_add}#${rule_group_set}"
done
if [ -n "$rule_group_add" ]; then
new_group_name="$new_group_name$rule_group_add"
unset rule_group_add
else
errornum
sleep 1
fi
;;
esac
}
while true; do
echo "-----------------------------------------------"
echo -e "\033[33m你可以在这里快捷管理自定义策略组\033[0m"
echo -e "\033[36m如需修改或批量操作请手动编辑$YAMLSDIR/proxy-groups.yaml\033[0m"
echo "-----------------------------------------------"
echo -e " 1 添加自定义策略组"
echo -e " 2 查看自定义策略组"
echo -e " 3 清空自定义策略组"
echo -e " 0 返回上级菜单"
read -r -p "请输入对应数字 > " num
case "$num" in
"" | 0)
break
;;
1)
group_type="select url-test fallback load-balance"
group_type_cn="手动选择 自动选择 故障转移 负载均衡"
proxy_group="$(cat "$YAMLSDIR"/proxy-groups.yaml "$YAMLSDIR"/config.yaml 2>/dev/null | sed "/#自定义策略组开始/,/#自定义策略组结束/d" | grep -Ev '^#' | grep -o '\- name:.*' | sed 's/#.*//' | sed 's/- name: /#/g' | tr -d '\n' | sed 's/#//')"
set_group_type
;;
2)
echo "-----------------------------------------------"
cat "$YAMLSDIR"/proxy-groups.yaml
;;
3)
read -p "确认清空全部自定义策略组?(1/0) > " res
[ "$res" = "1" ] && echo '#用于添加自定义策略组' >"$YAMLSDIR"/proxy-groups.yaml
;;
*)
errornum
sleep 1
;;
esac
done
}
setproxies() { # 自定义clash节点
set_proxy_type() {
echo "-----------------------------------------------"
echo -e "\033[33m注意节点格式必须是单行,不包括括号,name:必须写在最前,例如:\033[0m"
echo -e "\033[36m【name: \"test\", server: 192.168.1.1, port: 12345, type: socks5, udp: true】\033[0m"
echo -e "更多写法请参考:\033[32m https://juewuy.github.io/ \033[0m"
read -r -p "请输入节点 > " proxy_state_set
if echo "$proxy_state_set" | grep -q "#"; then
echo -e "\033[33m绝对禁止包含【#】号!!!\033[0m"
elif echo "$proxy_state_set" | grep -Eq "^name:"; then
set_group_add
else
errornum
sleep 1
fi
}
set_group_add() {
echo "-----------------------------------------------"
echo -e "\033[36m请选择想要将节点添加到的策略组\033[0m"
echo -e "\033[32m如需添加到多个策略组请一次性输入多个数字并用空格隔开\033[0m"
echo -e "\033[33m如需自定义策略组请先使用【管理自定义策略组功能】添加\033[0m"
echo "-----------------------------------------------"
echo "$proxy_group" | awk -F '#' '{for(i=1;i<=NF;i++){print i" "$i}}'
echo "-----------------------------------------------"
echo -e " 0 返回上级菜单"
read -r -p "请输入对应数字(多个用空格隔开) > " char
case "$char" in
"" | 0) ;;
*)
for num in $char; do
rule_group_set=$(echo "$proxy_group" | cut -d'#' -f"$num")
rule_group_add="${rule_group_add}#${rule_group_set}"
done
if [ -n "$rule_group_add" ]; then
echo "- {$proxy_state_set}$rule_group_add" >>"$YAMLSDIR"/proxies.yaml
echo "-----------------------------------------------"
echo -e "\033[32m添加成功\033[0m"
unset rule_group_add
else
errornum
sleep 1
fi
;;
esac
}
while true; do
echo "-----------------------------------------------"
echo -e "\033[33m你可以在这里快捷管理自定义节点\033[0m"
echo -e "\033[36m如需批量操作请手动编辑$YAMLSDIR/proxies.yaml\033[0m"
echo "-----------------------------------------------"
echo -e " 1 添加自定义节点"
echo -e " 2 管理自定义节点"
echo -e " 3 清空自定义节点"
echo -e " 4 配置节点绕过: \033[36m$proxies_bypass\033[0m"
echo -e " 0 返回上级菜单"
read -r -p "请输入对应数字 > " num
case "$num" in
"" | 0)
break
;;
1)
proxy_type="DOMAIN-SUFFIX DOMAIN-KEYWORD IP-CIDR SRC-IP-CIDR DST-PORT SRC-PORT GEOIP GEOSITE IP-CIDR6 DOMAIN MATCH"
proxy_group="$(cat "$YAMLSDIR"/proxy-groups.yaml "$YAMLSDIR"/config.yaml 2>/dev/null | sed "/#自定义策略组开始/,/#自定义策略组结束/d" | grep -Ev '^#' | grep -o '\- name:.*' | sed 's/#.*//' | sed 's/- name: /#/g' | tr -d '\n' | sed 's/#//')"
set_proxy_type
;;
2)
echo "-----------------------------------------------"
sed -i '/^ *$/d' "$YAMLSDIR"/proxies.yaml 2>/dev/null
if [ -s "$YAMLSDIR"/proxies.yaml ]; then
echo -e "当前已添加的自定义节点为:"
cat "$YAMLSDIR"/proxies.yaml | grep -Ev '^#' | awk -F '[,,}]' '{print NR, $1, $NF}' | sed 's/- {//g'
echo "-----------------------------------------------"
echo -e "\033[33m输入节点对应数字可以移除对应节点\033[0m"
read -r -p "请输入对应数字 > " num
if [ "$num" -le $(cat "$YAMLSDIR"/proxies.yaml | grep -Ev '^#' | wc -l) ]; then
sed -i "$num{/^\s*[^#]/d}" "$YAMLSDIR"/proxies.yaml
else
errornum
fi
else
echo -e "请先添加自定义节点!"
sleep 1
fi
;;
3)
read -r -p "确认清空全部自定义节点?(1/0) > " res
[ "$res" = "1" ] && sed -i '/^\s*[^#]/d' "$YAMLSDIR"/proxies.yaml 2>/dev/null
;;
4)
echo "-----------------------------------------------"
if [ "$proxies_bypass" = "OFF" ]; then
echo -e "\033[33m本功能会自动将当前配置文件中的节点域名或IP设置为直连规则以防止出现双重流量\033[0m"
echo -e "\033[33m请确保下游设备使用的节点与ShellCrash中使用的节点相同否则无法生效\033[0m"
read -r -p "启用节点绕过?(1/0) > " res
[ "$res" = "1" ] && proxies_bypass=ON
else
proxies_bypass=OFF
fi
setconfig proxies_bypass "$proxies_bypass"
sleep 1
setrules
break
;;
*)
errornum
sleep 1
;;
esac
done
}
set_clash_adv(){ #自定义clash高级规则
[ ! -f "$YAMLSDIR"/user.yaml ] && cat > "$YAMLSDIR"/user.yaml <<EOF
#用于编写自定义设定(可参考https://lancellc.gitbook.io/clash/clash-config-file/general 或 https://docs.metacubex.one/function/general)
#端口之类请在脚本中修改,否则不会加载
#port: 7890
EOF
[ ! -f "$YAMLSDIR"/others.yaml ] && cat > "$YAMLSDIR"/others.yaml <<EOF
#用于编写自定义的锚点、入站、proxy-providers、sub-rules、rule-set、script等功能
#可参考 https://github.com/MetaCubeX/Clash.Meta/blob/Meta/docs/config.yaml 或 https://lancellc.gitbook.io/clash/clash-config-file/an-example-configuration-file
#此处内容会被添加在配置文件的“proxy-group”模块的末尾与“rules”模块之前的位置
#例如:
#proxy-providers:
#rule-providers:
#sub-rules:
#tunnels:
#script:
#listeners:
EOF
echo "-----------------------------------------------"
echo -e "\033[32m已经创建自定义设定文件$YAMLSDIR/user.yaml \033[0m"
echo -e "\033[33m可用于编写自定义的DNS等功能\033[0m"
echo "-----------------------------------------------"
echo -e "\033[32m已经创建自定义功能文件$YAMLSDIR/others.yaml \033[0m"
echo -e "\033[33m可用于编写自定义的锚点、入站、proxy-providers、sub-rules、rule-set、script等功能\033[0m"
echo "-----------------------------------------------"
echo -e "Windows下请\n使用\033[33mWinSCP软件\033[0m进行编辑\033[0m"
echo -e "MacOS下请\n使用\033[33mSecureFX软件\033[0m进行编辑\033[0m"
echo -e "Linux本机可\n使用\033[33mvim\033[0m进行编辑(路由设备可能不显示中文请勿使用)\033[0m"
}
set_singbox_adv(){ #自定义singbox配置文件
echo "-----------------------------------------------"
echo -e "支持覆盖脚本设置的模块有:\033[0m"
echo -e "\033[36mlog dns ntp certificate experimental\033[0m"
echo -e "支持与内置功能合并(但不可冲突)的模块有:\033[0m"
echo -e "\033[36mendpoints inbounds outbounds providers route services\033[0m"
echo -e "将相应json文件放入\033[33m$JSONSDIR\033[0m目录后即可在启动时自动加载"
echo "-----------------------------------------------"
echo -e "使用前请务必参考配置教程:\033[32;4m https://juewuy.github.io/nWTjEpkSK \033[0m"
}

View File

@@ -0,0 +1,91 @@
#!/bin/sh
# Copyright (C) Juewuy
[ -n "$__IS_MODULE_PROVIDERS" ] && return
__IS_MODULE_PROVIDERS=1
if [ "$crashcore" = singboxr ]; then
CORE_TYPE=singbox
else
CORE_TYPE=clash
fi
providers() {
while true; do
# 获取模版名称
if [ -z "$(grep "provider_temp_${CORE_TYPE}" "$CRASHDIR"/configs/ShellCrash.cfg)" ]; then
provider_temp_des=$(sed -n "1 p" "$CRASHDIR"/configs/${CORE_TYPE}_providers.list | awk '{print $1}')
else
provider_temp_file=$(grep "provider_temp_${CORE_TYPE}" "$CRASHDIR"/configs/ShellCrash.cfg | awk -F '=' '{print $2}')
provider_temp_des=$(grep "$provider_temp_file" "$CRASHDIR"/configs/${CORE_TYPE}_providers.list | awk '{print $1}')
[ -z "$provider_temp_des" ] && provider_temp_des=$provider_temp_file
fi
separator_line "-"
content_line "1) \033[32m生成\033[0m包含全部提供者的配置文件"
content_line "2) 选择\033[33m规则模版\033[0m \033[32m$provider_temp_des\033[0m"
content_line "3) \033[33m清理\033[0mproviders目录文件"
separator_line "-"
common_back
read -p "请输入对应字母或数字 > " num
case "$num" in
"" | 0)
break
;;
1)
separator_line "-"
if [ -s "$CRASHDIR"/configs/providers.cfg ] || [ -s "$CRASHDIR"/configs/providers_uri.cfg ]; then
. "$CRASHDIR/menus/providers_$CORE_TYPE.sh"
gen_providers
else
content_line "\033[31m你还未添加链接或本地配置文件请先添加\033[0m"
sleep 1
fi
;;
2)
list=$(cat "$CRASHDIR/configs/${CORE_TYPE}_providers.list" | awk '{print $1}')
separator_line "-"
content_line "当前规则模版为:\033[32m$provider_temp_des\033[0m"
content_line "\033[33m请选择在线模版\033[0m"
separator_line "-"
list_box "$list"
separator_line "-"
content_line "a) 使用\033[36m本地模版\033[0m"
common_back
read -p "请输入对应字母或数字 > " num
case "$num" in
"" | 0) ;;
a)
read -p "请输入模版的路径(绝对路径) > " dir
if [ -s $dir ]; then
provider_temp_file=$dir
setconfig provider_temp_"$CORE_TYPE" "$provider_temp_file"
content_line "\033[32m设置成功\033[0m"
else
content_line "\033[31m输入错误找不到对应模版文件\033[0m"
fi
sleep 1
;;
*)
provider_temp_file=$(sed -n "$num p" "$CRASHDIR"/configs/${CORE_TYPE}_providers.list 2>/dev/null | awk '{print $2}')
if [ -z "$provider_temp_file" ]; then
errornum
sleep 1
else
setconfig provider_temp_"$CORE_TYPE" "$provider_temp_file"
fi
;;
esac
;;
3)
content_line "\033[33m将清空 $CRASHDIR/providers 目录下所有内容\033[0m"
read -p "是否继续?(1/0) > " res
[ "$res" = "1" ] && rm -rf "$CRASHDIR"/providers && common_success
;;
*)
errornum
sleep 1
break
;;
esac
done
}

View File

@@ -0,0 +1,123 @@
#!/bin/sh
# Copyright (C) Juewuy
[ -n "$__IS_PROVIDERS_CLASH" ] && return
__IS_PROVIDERS_CLASH=1
. "$CRASHDIR"/libs/web_get_bin.sh
#生成clash的providers配置文件
gen_providers(){
if [ -z "$(grep "provider_temp_${CORE_TYPE}" "$CRASHDIR"/configs/ShellCrash.cfg)" ];then
provider_temp_file="$(sed -n "1 p" "$CRASHDIR"/configs/${CORE_TYPE}_providers.list | awk '{print $2}')"
else
provider_temp_file=$(grep "provider_temp_${CORE_TYPE}" "$CRASHDIR"/configs/ShellCrash.cfg | awk -F '=' '{print $2}')
fi
echo "-----------------------------------------------"
if [ -s "$provider_temp_file" ];then
ln -sf "$provider_temp_file" "$TMPDIR"/provider_temp_file
else
echo -e "\033[33m正在获取在线模版\033[0m"
get_bin "$TMPDIR"/provider_temp_file "rules/${CORE_TYPE}_providers/$provider_temp_file"
[ -z "$(grep -o 'rules' "$TMPDIR"/provider_temp_file)" ] && {
echo -e "\033[31m下载失败请尝试更换安装源\033[0m"
. "$CRASHDIR"/menus/9_upgrade.sh && setserver
setproviders
}
fi
#生成proxy_providers模块
mkdir -p "$TMPDIR"/providers
#预创建文件并写入对应文件头
echo 'proxy-providers:' > "$TMPDIR"/providers/providers.yaml
#切割模版文件
sed -n '/^proxy-groups:/,/^[a-z]/ { /^rule/d; p; }' "$TMPDIR"/provider_temp_file > "$TMPDIR"/providers/proxy-groups.yaml
sed -n '/^rule/,$p' "$TMPDIR"/provider_temp_file > "$TMPDIR"/providers/rules.yaml
rm -rf "$TMPDIR"/provider_temp_file
#基于单订阅生成providers模块
if [ -n "$1" ];then
gen_providers_txt $@
providers_tags=$1
else
#基于全部订阅/本地文件生成
[ -s "$CRASHDIR"/configs/providers.cfg ] && {
providers_tags=''
while read line;do
gen_providers_txt $line
providers_tags=$(echo "$providers_tags, $tag" | sed 's/^, //')
done < "$CRASHDIR"/configs/providers.cfg
}
#基于全部节点分享链接生成
[ -s "$CRASHDIR"/configs/providers_uri.cfg ] && {
mkdir -p "$CRASHDIR"/providers
awk '{ print ($1=="vmess" ? $2 : $2 "#" $1) }' "$CRASHDIR"/configs/providers_uri.cfg > "$CRASHDIR"/providers/uri_group
gen_providers_txt "Uri_group" "./providers/uri_group" "3" "12"
providers_tags=$(echo "$providers_tags, Uri_group" | sed 's/^, //')
}
fi
#修饰模版文件并合并
sed -i "s/{providers_tags}/$providers_tags/g" "$TMPDIR"/providers/proxy-groups.yaml
cut -c 1- "$TMPDIR"/providers/providers.yaml "$TMPDIR"/providers/proxy-groups.yaml "$TMPDIR"/providers/rules.yaml > "$TMPDIR"/config.yaml
rm -rf "$TMPDIR"/providers
#调用内核测试
. "$CRASHDIR"/starts/check_core.sh && check_core && "$TMPDIR"/CrashCore -t -d "$BINDIR" -f "$TMPDIR"/config.yaml
if [ "$?" = 0 ];then
echo -e "\033[32m配置文件生成成功\033[0m"
mkdir -p "$CRASHDIR"/yamls
mv -f "$TMPDIR"/config.yaml "$CRASHDIR"/yamls/config.yaml
read -p "是否立即启动/重启服务?(1/0) > " res
[ "$res" = 1 ] && {
start_core && . "$CRASHDIR"/libs/set_cron.sh && cronset '更新订阅'
exit
}
else
rm -rf "$TMPDIR"/CrashCore
rm -rf "$TMPDIR"/config.yaml
echo -e "\033[31m生成配置文件出错请仔细检查输入\033[0m"
fi
}
gen_providers_txt(){
if [ -n "$(echo $2|grep -E '^./')" ];then
type=file
path=$2
download_url=
else
type=http
path="./providers/$1.yaml"
download_url=$2
fi
tag=$1
interval=${3:-3}
interval2=${4:-12}
ua=${5:-clash.meta}
exclude=${6#\#}
include=${7#\#}
cat >> "$TMPDIR"/providers/providers.yaml <<EOF
${1}:
type: $type
url: "$download_url"
path: "$path"
interval: $((interval2 * 3600))
health-check:
enable: true
lazy: true
url: "https://www.gstatic.com/generate_204"
interval: $((interval * 60))
EOF
[ "$crashcore" = 'meta' ] && {
[ "$skip_cert" != "OFF" ] && skip_cert_verify='skip-cert-verify: true'
cat >> "$TMPDIR"/providers/providers.yaml <<EOF
header:
User-Agent: ["$ua"]
override:
udp: true
$skip_cert_verify
filter: "$include"
exclude-filter: "$exclude"
EOF
}
#写入提供者
echo ' - {name: '"$tag"', type: url-test, tolerance: 100, lazy: true, use: ['"$tag"']}' >> "$TMPDIR"/providers/proxy-groups.yaml
}

View File

@@ -0,0 +1,129 @@
#!/bin/sh
# Copyright (C) Juewuy
[ -n "$__IS_PROVIDERS_SINGBOX" ] && return
__IS_PROVIDERS_SINGBOX=1
. "$CRASHDIR"/libs/web_get_bin.sh
#生成singbox的providers配置文件
gen_providers(){
if [ -z "$(grep "provider_temp_${CORE_TYPE}" "$CRASHDIR"/configs/ShellCrash.cfg)" ];then
provider_temp_file="$(sed -n "1 p" "$CRASHDIR"/configs/${CORE_TYPE}_providers.list | awk '{print $2}')"
else
provider_temp_file=$(grep "provider_temp_${CORE_TYPE}" "$CRASHDIR"/configs/ShellCrash.cfg | awk -F '=' '{print $2}')
fi
echo "-----------------------------------------------"
if [ -s "$provider_temp_file" ];then
ln -sf "$provider_temp_file" "$TMPDIR"/provider_temp_file
else
echo -e "\033[33m正在获取在线模版\033[0m"
get_bin "$TMPDIR"/provider_temp_file "rules/${CORE_TYPE}_providers/$provider_temp_file"
[ -z "$(grep -o 'route' "$TMPDIR"/provider_temp_file)" ] && {
echo -e "\033[31m下载失败请尝试更换安装源\033[0m"
. "$CRASHDIR"/menus/9_upgrade.sh && setserver
setproviders
}
fi
#生成outbound_providers模块
mkdir -p "$TMPDIR"/providers
#预创建文件并写入对应文件头
cat > "$TMPDIR"/providers/providers.json <<EOF
{
"providers": [
EOF
cat > "$TMPDIR"/providers/outbounds_add.json <<EOF
{
"outbounds": [
EOF
#基于单订阅生成providers模块
if [ -n "$1" ];then
gen_providers_txt $@
providers_tags=\"$1\"
else
#基于全部订阅/本地文件生成
[ -s "$CRASHDIR"/configs/providers.cfg ] && {
providers_tags=''
while read line;do
gen_providers_txt $line
providers_tags=$(echo "$providers_tags, \"$tag\"" | sed 's/^, //')
done < "$CRASHDIR"/configs/providers.cfg
}
#基于全部节点分享链接生成
[ -s "$CRASHDIR"/configs/providers_uri.cfg ] && {
mkdir -p "$CRASHDIR"/providers
awk '{ print ($1=="vmess" ? $2 : $2 "#" $1) }' "$CRASHDIR"/configs/providers_uri.cfg > "$CRASHDIR"/providers/uri_group
gen_providers_txt "Uri_group" "./providers/uri_group" "3" "12"
providers_tags=$(echo "$providers_tags, \"Uri_group\"" | sed 's/^, //')
}
fi
#修复文件格式
sed -i '$s/},/}]}/' "$TMPDIR"/providers/outbounds_add.json
sed -i '$s/},/}]}/' "$TMPDIR"/providers/providers.json
#使用模版生成outbounds和rules模块
cat "$TMPDIR"/provider_temp_file | sed "s/{providers_tags}/$providers_tags/g" | sed "s/\"providers_tags\"/$providers_tags/g" > "$TMPDIR"/providers/outbounds.json
rm -rf "$TMPDIR"/provider_temp_file
#调用内核测试
. "$CRASHDIR"/starts/check_core.sh && check_core && "$TMPDIR"/CrashCore merge "$TMPDIR"/config.json -C "$TMPDIR"/providers
if [ "$?" = 0 ];then
echo -e "\033[32m配置文件生成成功如果启动超时建议更新里手动安装Singbox-srs数据库常用包\033[0m"
mkdir -p "$CRASHDIR"/jsons
mv -f "$TMPDIR"/config.json "$CRASHDIR"/jsons/config.json
rm -rf "$TMPDIR"/providers
read -p "是否立即启动/重启服务?(1/0) > " res
[ "$res" = 1 ] && {
start_core && . "$CRASHDIR"/libs/set_cron.sh && cronset '更新订阅'
exit
}
else
echo -e "\033[31m生成配置文件出错请仔细检查输入\033[0m"
rm -rf "$TMPDIR"/CrashCore
#rm -rf "$TMPDIR"/providers
fi
}
gen_providers_txt(){
tag=$1
interval=${3:-3}
interval2=${4:-12}
ua=${5:-clash.meta}
exclude=${6#\#}
include=${7#\#}
if [ -n "$(echo $2|grep -E '^./')" ];then
cat >> "$TMPDIR"/providers/providers.json <<EOF
{
"tag": "$tag",
"type": "local",
"path": "$2",
EOF
else
cat >> "$TMPDIR"/providers/providers.json <<EOF
{
"tag": "$tag",
"type": "remote",
"url": "$2",
"path": "./providers/$tag.yaml",
"user_agent": "$ua",
"update_interval": "${interval2}h",
"exclude": "$exclude",
"include": "$include",
EOF
fi
#通用部分生成
[ "$skip_cert" != "OFF" ] && override_tls='true' || override_tls='false'
cat >> "$TMPDIR"/providers/providers.json <<EOF
"health_check": {
"enabled": true,
"url": "https://www.gstatic.com/generate_204",
"interval": "${interval}m",
"timeout": "3s"
},
"override_tls": {
"enabled": true,
"insecure": $override_tls
}
},
EOF
#写入提供者
echo '{ "tag": "'"$tag"'", "type": "urltest", "tolerance": 100, "providers": ["'"$tag"'"], "include": ".*" },' >> "$TMPDIR"/providers/outbounds_add.json
}

View File

@@ -0,0 +1,13 @@
running_status(){
VmRSS=$(awk '/^VmRSS:/ {printf "%.2f MB\n", ($2 * 1024) / 1000000}' /proc/$PID/status)
#获取运行时长
touch "$TMPDIR"/crash_start_time #用于延迟启动的校验
start_time=$(cat "$TMPDIR"/crash_start_time)
if [ -n "$start_time" ]; then
time=$(($(date +%s) - start_time))
day=$((time / 86400))
[ "$day" = "0" ] && day='' || day="$dayD"
time=$(date -u -d @${time} +%H:%M:%S)
fi
}

View File

@@ -0,0 +1,157 @@
#!/bin/sh
# Copyright (C) Juewuy
#. /tmp/SC_tmp/libs/check_dir_avail.sh
cecho() {
printf '%b\n' "$*"
}
set_usb_dir() {
while true; do
cecho "请选择安装目录"
du -hL /mnt | awk '{print " "NR" "$2" "$1}'
read -p "请输入相应数字 > " num
dir=$(du -hL /mnt | awk '{print $2}' | sed -n "$num"p)
if [ -z "$dir" ]; then
cecho "\033[31m输入错误请重新设置\033[0m"
continue
fi
break 1
done
}
set_xiaomi_dir() {
cecho "\033[33m检测到当前设备为小米官方系统请选择安装位置\033[0m"
[ -d /data ] && cecho " 1 安装到 /data 目录,剩余空间:$(dir_avail /data -h)(支持软固化功能)"
[ -d /userdisk ] && cecho " 2 安装到 /userdisk 目录,剩余空间:$(dir_avail /userdisk -h)(支持软固化功能)"
[ -d /data/other_vol ] && cecho " 3 安装到 /data/other_vol 目录,剩余空间:$(dir_avail /data/other_vol -h)(支持软固化功能)"
cecho " 4 安装到自定义目录(不推荐,不明勿用!)"
cecho " 0 退出安装"
echo "-----------------------------------------------"
read -p "请输入相应数字 > " num
case "$num" in
1)
dir=/data
;;
2)
dir=/userdisk
;;
3)
dir=/data/other_vol
;;
4)
set_cust_dir
;;
*)
exit 1
;;
esac
}
set_asus_usb() {
while true; do
echo -e "请选择U盘目录"
du -hL /tmp/mnt | awk -F/ 'NF<=4' | awk '{print " "NR" "$2" "$1}'
read -p "请输入相应数字 > " num
dir=$(du -hL /tmp/mnt | awk -F/ 'NF<=4' | awk '{print $2}' | sed -n "$num"p)
if [ ! -f "$dir/asusware.arm/etc/init.d/S50downloadmaster" ]; then
echo -e "\033[31m未找到下载大师自启文件$dir/asusware.arm/etc/init.d/S50downloadmaster请检查设置\033[0m"
sleep 1
else
break
fi
done
}
set_asus_dir() {
cecho "\033[33m检测到当前设备为华硕固件请选择安装方式\033[0m"
cecho " 1 基于U盘+下载大师安装(支持所有固件限ARM设备须插入U盘或移动硬盘)"
cecho " 2 基于自启脚本安装(仅支持部分梅林固件)"
cecho " 0 退出安装"
echo "-----------------------------------------------"
read -p "请输入相应数字 > " num
case "$num" in
1)
echo -e "请先在路由器网页后台安装下载大师并启用,之后选择外置存储所在目录!"
sleep 2
set_asus_usb
;;
2)
cecho "如开机无法正常自启请重新使用U盘+下载大师安装!"
sleep 2
dir=/jffs
;;
*)
exit 1
;;
esac
}
set_cust_dir() {
while true; do
echo "-----------------------------------------------"
echo '可用路径 剩余空间:'
df -h | awk '{print $6,$4}' | sed 1d
echo '路径是必须带 / 的格式,注意写入虚拟内存(/tmp,/opt,/sys...)的文件会在重启后消失!!!'
read -p "请输入自定义路径 > " dir
if [ "$(dir_avail "$dir")" = 0 ] || [ -n "$(echo "$dir" | grep -Eq '^/(tmp|opt|sys)(/|$)')" ]; then
cecho "\033[31m路径错误请重新设置\033[0m"
continue
fi
break 1
done
}
set_crashdir() {
while true; do
echo "-----------------------------------------------"
cecho "\033[33m注意安装ShellCrash至少需要预留约1MB的磁盘空间\033[0m"
case "$systype" in
Padavan) dir=/etc/storage ;;
mi_snapshot) set_xiaomi_dir ;;
asusrouter) set_asus_dir ;;
ng_snapshot) dir=/tmp/mnt ;;
*)
cecho " 1 在\033[32m/etc目录\033[0m下安装(适合root用户)"
cecho " 2 在\033[32m/usr/share目录\033[0m下安装(适合Linux系统)"
cecho " 3 在\033[32m当前用户目录\033[0m下安装(适合非root用户)"
cecho " 4 在\033[32m外置存储\033[0m中安装"
cecho " 5 手动设置安装目录"
cecho " 0 退出安装"
echo "----------------------------------------------"
read -p "请输入相应数字 > " num
# 设置目录
case "$num" in
1)
dir=/etc
;;
2)
dir=/usr/share
;;
3)
dir=~/.local/share
mkdir -p ~/.config/systemd/user
;;
4)
set_usb_dir
;;
5)
set_cust_dir
;;
*)
echo "安装已取消"
exit 1
;;
esac
;;
esac
if [ ! -w "$dir" ]; then
cecho "\033[31m没有$dir目录写入权限!请重新设置!\033[0m"
sleep 1
else
cecho "目标目录\033[32m$dir\033[0m空间剩余$(dir_avail "$dir" -h)"
read -p "确认安装?(1/0) > " res
if [ "$res" = "1" ]; then
CRASHDIR="$dir"/ShellCrash
break
fi
fi
done
}

View File

@@ -0,0 +1,177 @@
#!/bin/sh
# Copyright (C) Juewuy
[ -n "$__IS_MODULE_SUBCONVERTER" ] && return
__IS_MODULE_SUBCONVERTER=1
[ -z "$rule_link" ] && rule_link=1
[ -z "$server_link" ] && server_link=1
#Subconverter在线订阅转换
subconverter() {
while true; do
separator_line "-"
content_line "1) \033[32m生成\033[0m包含全部节点/订阅的配置文件"
content_line "2) 设置\033[31m排除节点正则\033[0m \033[47;30m$exclude\033[0m"
content_line "3) 设置\033[32m包含节点正则\033[0m \033[47;30m$include\033[0m"
content_line "4) 选择\033[33m在线规则模版\033[0m"
content_line "5) 选择\033[0mSubconverter服务器\033[0m"
content_line "6) 自定义浏览器UA \033[32m$user_agent\033[0m"
common_back
read -r -p "请输入对应数字 > " num
case "$num" in
"" | 0)
break
;;
1)
providers_link=$(grep -v '\./providers/' "$CRASHDIR"/configs/providers.cfg 2>/dev/null |awk '{print $2}' |paste -sd '|')
uri_link=$(grep -v '^#' "$CRASHDIR"/configs/providers_uri.cfg 2>/dev/null |awk '{ print ($1=="vmess" ? $2 : $2 "#" $1) }' |paste -sd '|')
Url=$(echo "$providers_link|$uri_link" |sed 's/^|// ; s/|$//')
setconfig Url "'$Url'"
Https=''
setconfig Https
# 获取在线文件
jump_core_config
;;
2)
gen_link_flt
;;
3)
gen_link_ele
;;
4)
gen_link_config
;;
5)
gen_link_server
;;
6)
set_sub_ua
;;
*)
errornum
break
;;
esac
done
}
gen_link_flt() { # 排除节点正则
[ -z "$exclude" ] && exclude="未设置"
separator_line "-"
content_line "\033[33m当前过滤关键字\033[47;30m$exclude\033[0m"
separator_line "-"
content_line "\033[33m匹配关键字的节点会在导入时被【屏蔽】\033[0m"
content_line "多个关键字可以用\033[30;47m | \033[0m号分隔"
content_line "\033[32m支持正则表达式\033[0m空格请使用\033[30;47m + \033[0m号替代"
separator_line "-"
content_line " 000 \033[31m删除\033[0m关键字"
content_line " 回车 取消输入并返回上级菜单"
separator_line "-"
read -r -p "请输入关键字 > " exclude
if [ "$exclude" = '000' ]; then
separator_line "-"
exclude=''
content_line "\033[31m 已删除节点过滤关键字!!!\033[0m"
fi
setconfig exclude "'$exclude'"
}
gen_link_ele() { # 包含节点正则
[ -z "$include" ] && include="未设置"
separator_line "-"
content_line "\033[33m当前筛选关键字\033[47;30m$include\033[0m"
separator_line "-"
content_line "\033[33m仅有匹配关键字的节点才会被【导入】\033[0m"
content_line "多个关键字可以用\033[30;47m | \033[0m号分隔"
content_line "\033[32m支持正则表达式\033[0m空格请使用\033[30;47m + \033[0m号替代"
separator_line "-"
content_line " 000 \033[31m删除\033[0m关键字"
content_line " 回车 取消输入并返回上级菜单"
separator_line "-"
read -r -p "请输入关键字 > " include
if [ "$include" = '000' ]; then
separator_line "-"
include=''
content_line "\033[31m 已删除节点匹配关键字!!!\033[0m"
fi
setconfig include "'$include'"
}
gen_link_config() { #选择在线规则模版
list=$(grep -aE '^5' "$CRASHDIR"/configs/servers.list | awk '{print $2$4}')
now=$(grep -aE '^5' "$CRASHDIR"/configs/servers.list | sed -n ""$rule_link"p" | awk '{print $2}')
separator_line "-"
content_line "当前使用规则为:\033[33m$now\033[0m"
separator_line "-"
list_box "$list"
separator_line "-"
common_back
read -r -p "请输入对应数字 > " num
totalnum=$(grep -acE '^5' "$CRASHDIR"/configs/servers.list )
if [ -z "$num" ] || [ "$num" -gt "$totalnum" ];then
errornum
elif [ "$num" = 0 ];then
echo
elif [ "$num" -le "$totalnum" ];then
#将对应标记值写入配置
rule_link=$num
setconfig rule_link $rule_link
separator_line "-"
content_line "\033[32m设置成功返回上级菜单\033[0m"
fi
}
gen_link_server() { #选择Subconverter服务器
list=$(grep -aE '^3|^4' "$CRASHDIR"/configs/servers.list | awk '{print $3" "$2}')
now=$(grep -aE '^3|^4' "$CRASHDIR"/configs/servers.list | sed -n ""$server_link"p" | awk '{print $3}')
separator_line "-"
content_line "\033[36m以下为互联网采集的第三方服务器具体安全性请自行斟酌\033[0m"
content_line "\033[32m感谢以下作者的无私奉献\033[0m"
content_line "当前使用后端为:\033[33m$now\033[0m"
separator_line "-"
list_box "$list"
common_back
read -r -p "请输入对应数字 > " num
totalnum=$(grep -acE '^3|^4' "$CRASHDIR"/configs/servers.list )
if [ -z "$num" ] || [ "$num" -gt "$totalnum" ];then
errornum
elif [ "$num" = 0 ];then
echo
elif [ "$num" -le "$totalnum" ];then
#将对应标记值写入配置
server_link=$num
setconfig server_link $server_link
separator_line "-"
content_line "\033[32m设置成功返回上级菜单\033[0m"
fi
}
set_sub_ua() {
separator_line "-"
content_line "\033[36m无法正确获取配置文件时可尝试使用\033[0m"
content_line " 1 使用自动UA(默认)"
content_line " 2 不使用UA"
content_line " 3 使用自定义UA\033[32m$user_agent\033[0m"
separator_line "-"
read -r -p "请输入对应数字 > " num
case "$num" in
0)
user_agent=''
;;
1)
user_agent='auto'
;;
2)
user_agent='none'
;;
3)
read -r -p "请输入自定义UA(不要包含空格和特殊符号!) > " text
[ -n "$text" ] && user_agent="$text"
;;
*)
errornum
;;
esac
[ "$num" -le 3 ] && setconfig user_agent "$user_agent"
}

145
scripts/menus/task_cmd.sh Normal file
View File

@@ -0,0 +1,145 @@
#!/bin/sh
# Copyright (C) Juewuy
#加载全局变量
[ -z "$CRASHDIR" ] && CRASHDIR=$( cd $(dirname $0);cd ..;pwd)
. "$CRASHDIR"/libs/get_config.sh
#加载工具
. "$CRASHDIR"/libs/check_cmd.sh
. "$CRASHDIR"/libs/set_config.sh
. "$CRASHDIR"/libs/web_get_bin.sh
. "$CRASHDIR"/libs/logger.sh
task_logger(){
[ "$task_push" = 1 ] && push= || push=off
[ -n "$2" -a "$2" != 0 ] && echo -e "\033[$2m$1\033[0m"
[ "$3" = 'off' ] && push=off
echo "$1" |grep -qE '(每隔|时每)([1-9]|[1-9][0-9])分钟' || logger "$1" 0 "$push"
}
#任务命令
check_update(){ #检查更新工具
get_bin "$TMPDIR"/crashversion "$1" echooff
[ "$?" = "0" ] && . "$TMPDIR"/crashversion 2>/dev/null
rm -rf "$TMPDIR"/crashversion
}
update_core(){ #自动更新内核
#检查版本
check_update bin/version
crash_v_new=$(eval echo \$${crashcore}_v)
if [ -z "$crash_v_new" -o "$crash_v_new" = "$core_v" ];then
task_logger "任务【自动更新内核】中止-未检测到版本更新"
return 0
else
. "$CRASHDIR"/libs/core_webget.sh && core_webget #调用下载工具
case "$?" in
0)
task_logger "任务【自动更新内核】下载完成,正在重启服务!"
"$CRASHDIR"/start.sh start
return 0
;;
1)
task_logger "任务【自动更新内核】出错-下载失败!"
return 1
;;
*)
task_logger "任务【自动更新内核】出错-内核校验失败!"
"$CRASHDIR"/start.sh start
return 1
;;
esac
fi
}
update_scripts(){ #自动更新脚本
#检查版本
check_update version
if [ -z "$versionsh" -o "$versionsh" = "versionsh_l" ];then
task_logger "任务【自动更新脚本】中止-未检测到版本更新"
return 0
else
get_bin "$TMPDIR"/clashfm.tar.gz "bin/update.tar.gz"
if [ "$?" != "0" ];then
rm -rf "$TMPDIR"/clashfm.tar.gz
task_logger "任务【自动更新内核】出错-下载失败!"
return 1
else
#停止服务
"$CRASHDIR"/start.sh stop
#解压
tar -zxf "$TMPDIR"/clashfm.tar.gz ${tar_para} -C "$CRASHDIR"/
if [ $? -ne 0 ];then
rm -rf "$TMPDIR"/clashfm.tar.gz
task_logger "任务【自动更新内核】出错-解压失败!"
"$CRASHDIR"/start.sh start
return 1
else
. "$CRASHDIR"/init.sh >/dev/null
"$CRASHDIR"/start.sh start
return 0
fi
fi
fi
}
update_mmdb(){ #自动更新数据库
getgeo(){
#检查版本
check_update bin/version
geo_v="$(echo $2 | awk -F "." '{print $1}')_v" #获取版本号类型比如Country_v
geo_v_new=$GeoIP_v
geo_v_now=$(eval echo \$$geo_v)
if [ -z "$geo_v_new" -o "$geo_v_new" = "$geo_v_now" ];then
task_logger "任务【自动更新数据库文件】跳过-未检测到$2版本更新"
else
#更新文件
get_bin "$TMPDIR"/$1 "bin/geodata/$2"
if [ "$?" != "0" ];then
task_logger "任务【自动更新数据库文件】更新【$2】下载失败!"
rm -rf "$TMPDIR"/$1
else
mv -f "$TMPDIR"/$1 "$BINDIR"/$1
setconfig $geo_v $GeoIP_v
task_logger "任务【自动更新数据库文件】更新【$2】成功!"
fi
fi
}
[ -n "${cn_mini_v}" -a -s "$CRASHDIR"/Country.mmdb ] && getgeo Country.mmdb cn_mini.mmdb
[ -n "${china_ip_list_v}" -a -s "$CRASHDIR"/cn_ip.txt ] && getgeo cn_ip.txt china_ip_list.txt
[ -n "${china_ipv6_list_v}" -a -s "$CRASHDIR"/cn_ipv6.txt ] && getgeo cn_ipv6.txt china_ipv6_list.txt
[ -n "${geosite_v}" -a -s "$CRASHDIR"/GeoSite.dat ] && getgeo GeoSite.dat geosite.dat
[ -n "${geoip_cn_v}" -a -s "$CRASHDIR"/geoip.db ] && getgeo geoip.db geoip_cn.db
[ -n "${geosite_cn_v}" -a -s "$CRASHDIR"/geosite.db ] && getgeo geosite.db geosite_cn.db
return 0
}
reset_firewall(){ #重设透明路由防火墙
"$CRASHDIR"/start.sh stop_firewall
"$CRASHDIR"/start.sh afstart
}
ntp(){
[ "$crashcore" != singbox ] && ckcmd ntpd && ntpd -n -q -p 203.107.6.88 >/dev/null 2>&1 || exit 0
}
web_save_auto(){
. "$CRASHDIR"/libs/web_save.sh && web_save
}
update_config() { #更新订阅并重启
. "$CRASHDIR"/starts/core_config.sh && get_core_config && "$CRASHDIR"/start.sh start
}
hotupdate() { #热更新订阅
. "$CRASHDIR"/starts/core_config.sh && get_core_config &&
. "$CRASHDIR"/starts/check_core.sh && check_core &&
. "$CRASHDIR"/starts/"$target"_modify.sh && modify_"$format" && rm -rf "$TMPDIR"/CrashCore &&
. "$CRASHDIR"/libs/web_restore.sh && put_save "http://127.0.0.1:$db_port/configs" "{\"path\":\"$CRASHDIR/config.$format\"}"
exit $?
}
case "$1" in
[1-9][0-9][0-9])
task_command=$(cat "$CRASHDIR"/task/task.list "$CRASHDIR"/task/task.user 2>/dev/null | grep "$1" | awk -F '#' '{print $2}')
task_name=$(cat "$CRASHDIR"/task/task.list "$CRASHDIR"/task/task.user 2>/dev/null | grep "$1" | awk -F '#' '{print $3}')
#task_logger "任务$task_name 开始执行"
eval $task_command && task_res=成功 || task_res=失败
task_logger "任务【$2】执行$task_res"
;;
*)
"$1"
;;
esac

154
scripts/menus/tui_layout.sh Normal file
View File

@@ -0,0 +1,154 @@
# tui/layout.sh
# Terminal UI layout helpers
# Provides menu/table formatting utilities
# set the total width of the menu
# (adjusting this number will automatically change the entire menu, including the separator lines)
# note: The number represents the number of columns that appear when the "||" appears on the right
TABLE_WIDTH=60
# define two extra-long template strings in advance
# (the length should be greater than the expected TABLE_WIDTH)
FULL_EQ="===================================================================================================="
FULL_DASH="- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "
# function to print content lines
content_line() {
raw_input="$1"
if [ -z "$raw_input" ]; then
printf " \033[%dG||\n" "$TABLE_WIDTH"
return
fi
printf '%b' "$raw_input" | LC_ALL=C awk -v table_width="$TABLE_WIDTH" '
BEGIN {
textWidth = table_width - 3
currentDisplayWidth = 0
wordWidth = 0
currentLine = ""
wordBuffer = ""
lastColor = ""
savedColor = ""
ESC = sprintf("%c", 27)
}
{
n = split($0, chars, "")
for (i = 1; i <= n; i++) {
r = chars[i]
if (r == ESC && i+1 <= n && chars[i+1] == "[") {
ansiSeq = ""
for (j = i; j <= n; j++) {
ansiSeq = ansiSeq chars[j]
if (chars[j] == "m") {
i = j
break
}
}
wordBuffer = wordBuffer ansiSeq
lastColor = ansiSeq
continue
}
charWidth = 1
if (r <= "\177") { charWidth = 1 }
else if (r >= "\340" && r <= "\357" && i+2 <= n) {
r = chars[i] chars[i+1] chars[i+2]
i += 2
charWidth = 2
}
else if (r >= "\300" && r <= "\337" && i+1 <= n) {
r = chars[i] chars[i+1]
i += 1
charWidth = 1
}
if (r == " " || charWidth == 2) {
if (currentDisplayWidth + wordWidth + charWidth > textWidth) {
printf " %s\033[0m\033[%dG||\n", currentLine, table_width
currentLine = savedColor wordBuffer
currentDisplayWidth = wordWidth
wordBuffer = r
wordWidth = charWidth
savedColor = lastColor
} else {
currentLine = currentLine wordBuffer r
currentDisplayWidth += wordWidth + charWidth
wordBuffer = ""
wordWidth = 0
savedColor = lastColor
}
} else {
wordBuffer = wordBuffer r
wordWidth += charWidth
if (wordWidth > textWidth) {
printf " %s%s\033[0m\033[%dG||\n", currentLine, wordBuffer, table_width
currentLine = savedColor
currentDisplayWidth = 0
wordBuffer = ""
wordWidth = 0
savedColor = lastColor
}
}
}
if (wordWidth > 0) {
if (currentDisplayWidth + wordWidth > textWidth) {
printf " %s\033[0m\033[%dG||\n", currentLine, table_width
currentLine = savedColor wordBuffer
} else {
currentLine = currentLine wordBuffer
}
}
printf " %s\033[0m\033[%dG||\n", currentLine, table_width
currentLine = lastColor
currentDisplayWidth = 0
wordBuffer = ""
wordWidth = 0
savedColor = lastColor
}
END {}
'
}
# function for right side text
# color sould be disabled
content_right() {
content_line "$(printf "%$((${TABLE_WIDTH:-60} - 3))s" "$1")"
}
# function to print sub content lines
# for printing accompanying instructions
sub_content_line() {
param="$1"
if [ -z "$param" ]; then
printf " \033[%dG||\n" "$TABLE_WIDTH"
return
fi
content_line " $param"
printf " \033[%dG||\n" "$TABLE_WIDTH"
}
# function to print separators
# (using string slicing)
# parameter $1: pass in "=" or "-"
separator_line() {
separatorType="$1"
lenLimit=$((TABLE_WIDTH - 1))
outputLine=""
if [ "$separatorType" = "=" ]; then
outputLine=$(printf "%.${lenLimit}s" "$FULL_EQ")
else
outputLine=$(printf "%.${lenLimit}s" "$FULL_DASH")
fi
printf "%s||\n" "$outputLine"
}
# increase the spacing between the front
# and back forms to improve readability
line_break() {
printf "\n\n"
}

22
scripts/menus/tui_lite.sh Normal file
View File

@@ -0,0 +1,22 @@
TABLE_WIDTH=60
content_line() {
printf '%b' " $1\n"
}
content_right() {
printf "%$((TABLE_WIDTH - 13))s\n" "$1"
}
sub_content_line() {
content_line " $1"
}
separator_line() {
echo "-----------------------------------------------"
}
line_break() {
return
}

View File

@@ -0,0 +1,76 @@
#!/bin/sh
# Copyright (C) Juewuy
# 卸载
uninstall() {
comp_box "\033[31m警告\033[0m" \
"\033[31m该操作不可逆\033" \
"是否确认卸载ShellCrash"
content_line "1) 是"
content_line "0) 否"
separator_line "="
read -r -p "$COMMON_INPUT> " res
if [ "$res" = '1' ]; then
# 停止服务
"$CRASHDIR"/start.sh stop 2>/dev/null
"$CRASHDIR"/start.sh cronset "clash服务" 2>/dev/null
"$CRASHDIR"/start.sh cronset "订阅链接" 2>/dev/null
"$CRASHDIR"/start.sh cronset "ShellCrash初始化" 2>/dev/null
"$CRASHDIR"/start.sh cronset "task.sh" 2>/dev/null
# 移除安装目录
if [ -n "$CRASHDIR" ] && [ "$CRASHDIR" != '/' ]; then
comp_box "是否保留脚本配置及订阅文件:"
content_line "1) 是"
content_line "0) 否"
separator_line "="
read -r -p "$COMMON_INPUT> " res
if [ "$res" = '1' ]; then
mv -f "$CRASHDIR"/configs /tmp/ShellCrash/configs_bak
mv -f "$CRASHDIR"/yamls /tmp/ShellCrash/yamls_bak
mv -f "$CRASHDIR"/jsons /tmp/ShellCrash/jsons_bak
rm -rf "$CRASHDIR"/*
mv -f /tmp/ShellCrash/configs_bak "$CRASHDIR"/configs
mv -f /tmp/ShellCrash/yamls_bak "$CRASHDIR"/yamls
mv -f /tmp/ShellCrash/jsons_bak "$CRASHDIR"/jsons
else
rm -rf "$CRASHDIR"
fi
else
msg_alert "\033[31m环境变量配置有误请尝试手动移除安装目录\033[0m"
fi
# 移除其他内容
sed -i "/alias $my_alias=*/"d /etc/profile 2>/dev/null
sed -i '/alias crash=*/'d /etc/profile 2>/dev/null
sed -i '/export CRASHDIR=*/'d /etc/profile 2>/dev/null
sed -i '/export crashdir=*/'d /etc/profile 2>/dev/null
[ -w ~/.zshrc ] && {
sed -i "/alias $my_alias=*/"d ~/.zshrc 2>/dev/null
sed -i '/export CRASHDIR=*/'d ~/.zshrc 2>/dev/null
}
sed -i '/all_proxy/'d /etc/profile 2>/dev/null
sed -i '/ALL_PROXY/'d /etc/profile 2>/dev/null
sed -i "/启用外网访问SSH服务/d" /etc/firewall.user 2>/dev/null
sed -i '/ShellCrash初始化/'d /etc/storage/started_script.sh 2>/dev/null
sed -i '/ShellCrash初始化/'d /jffs/.asusrouter 2>/dev/null
[ "$BINDIR" != "$CRASHDIR" ] && rm -rf "$BINDIR"
rm -rf /etc/init.d/shellcrash
rm -rf /etc/systemd/system/shellcrash.service
rm -rf /usr/lib/systemd/system/shellcrash.service
rm -rf /www/clash
rm -rf /tmp/ShellCrash
rm -rf /usr/bin/crash
sed -i '/0:7890/d' /etc/passwd 2>/dev/null
userdel -r shellcrash 2>/dev/null
nvram set script_usbmount="" 2>/dev/null
nvram commit 2>/dev/null
comp_box "\033[36m已卸载ShellCrash相关文件有缘再会\033[0m" \
"\033[33m请手动关闭当前窗口以重置环境变量\033[0m"
line_break
sleep 1
exit 0
else
msg_alert "\033[31m操作已取消\033[0m"
fi
}

141
scripts/menus/userguide.sh Normal file
View File

@@ -0,0 +1,141 @@
#!/bin/sh
# Copyright (C) Juewuy
[ -n "$__IS_MODULE_USERGUIDE_LOADED" ] && return
__IS_MODULE_USERGUIDE_LOADED=1
forwhat() {
while true; do
echo "-----------------------------------------------"
echo -e "\033[30;46m 欢迎使用ShellCrash新手引导 \033[0m"
echo "-----------------------------------------------"
echo -e "\033[33m请先选择你的使用环境 \033[0m"
echo -e "\033[0m(你之后依然可以在设置中更改各种配置)\033[0m"
echo "-----------------------------------------------"
echo -e " 1 \033[32m路由设备配置局域网透明代理\033[0m"
echo -e " 2 \033[36mLinux设备仅配置本机代理\033[0m"
[ -f "$CFG_PATH.bak" ] && echo -e " 3 \033[33m还原之前备份的设置\033[0m"
echo "-----------------------------------------------"
read -r -p "请输入对应数字 > " num
case "$num" in
"" | 1)
# 设置运行模式
redir_mod="Mix"
echo "$cputype" | grep -Eq 'linux.*mips.*' && {
if grep -qE '^TPROXY$' /proc/net/ip_tables_targets || modprobe xt_TPROXY >/dev/null 2>&1; then
redir_mod="Tproxy"
else
redir_mod="Redir"
fi
}
[ -z "$crashcore" ] && crashcore=meta
setconfig crashcore "$crashcore"
setconfig redir_mod "$redir_mod"
setconfig dns_mod mix
setconfig firewall_area '1'
# 默认启用绕过CN-IP
setconfig cn_ip_route ON
# 自动识别IPV6
[ -n "$(ip a 2>&1 | grep -w 'inet6' | grep -E 'global' | sed 's/.*inet6.//g' | sed 's/scope.*$//g')" ] && {
setconfig ipv6_redir ON
setconfig ipv6_support ON
setconfig ipv6_dns ON
setconfig cn_ipv6_route ON
}
# 设置开机启动
if [ -f /etc/rc.common ] && [ "$(cat /proc/1/comm)" = "procd" ]; then
/etc/init.d/shellcrash enable
fi
ckcmd systemctl && [ "$(cat /proc/1/comm)" = "systemd" ] && systemctl enable shellcrash.service >/dev/null 2>&1
rm -rf "$CRASHDIR"/.dis_startup
autostart=enable
# 检测IP转发
if [ "$(cat /proc/sys/net/ipv4/ip_forward)" = "0" ]; then
echo "-----------------------------------------------"
echo -e "\033[33m检测到你的设备尚未开启ip转发局域网设备将无法正常连接网络是否立即开启\033[0m"
read -r -p "是否开启?(1/0) > " res
[ "$res" = 1 ] && {
echo 'net.ipv4.ip_forward = 1' >>/etc/sysctl.conf
sysctl -w net.ipv4.ip_forward=1
} && echo "已成功开启ipv4转发如未正常开启请手动重启设备" || echo "开启失败!请自行谷歌查找当前设备的开启方法!"
fi
# 禁止docker启用的net.bridge.bridge-nf-call-iptables
sysctl -w net.bridge.bridge-nf-call-iptables=0 >/dev/null 2>&1
sysctl -w net.bridge.bridge-nf-call-ip6tables=0 >/dev/null 2>&1
break
;;
2)
setconfig redir_mod "Redir"
echo "$cputype" | grep -Eq "linux.*mips.*" && setconfig crashcore "clash"
setconfig common_ports "OFF"
setconfig firewall_area '2'
break
;;
3)
mv -f "$CFG_PATH.bak" "$CFG_PATH"
echo -e "\033[32m脚本设置已还原\033[0m"
echo -e "\033[33m请重新启动脚本\033[0m"
exit 0
;;
*)
errornum
sleep 1
;;
esac
done
}
# 新手引导
userguide() {
. "$CRASHDIR"/libs/check_dir_avail.sh
forwhat
# 检测小内存模式
dir_size=$(dir_avail "$CRASHDIR")
if [ "$dir_size" -lt 10240 ]; then
echo "-----------------------------------------------"
echo -e "\033[33m检测到你的安装目录空间不足10M是否开启小闪存模式\033[0m"
echo -e "\033[0m开启后核心及数据库文件将被下载到内存中这将占用一部分内存空间\033[0m"
echo -e "\033[0m每次开机后首次运行服务时都会自动的重新下载相关文件\033[0m"
echo "-----------------------------------------------"
read -r -p "是否开启?(1/0) > " res
[ "$res" = 1 ] && {
BINDIR=/tmp/ShellCrash
setconfig BINDIR /tmp/ShellCrash "$CRASHDIR"/configs/command.env
}
fi
# 启用推荐的自动任务配置
. "$CRASHDIR"/menus/5_task.sh && task_recom
# 小米设备软固化
if [ "$systype" = "mi_snapshot" ]; then
echo "-----------------------------------------------"
echo -e "\033[33m检测到为小米路由设备启用软固化可防止路由升级后丢失SSH\033[0m"
read -r -p "是否启用软固化功能?(1/0) > " res
[ "$res" = 1 ] && mi_autoSSH
fi
# 提示导入订阅或者配置文件
if [ ! -s "$CRASHDIR"/yamls/config.yaml ] && [ ! -s "$CRASHDIR"/jsons/config.json ]; then
echo "-----------------------------------------------"
echo -e "\033[32m是否导入配置文件\033[0m(这是运行前的最后一步)"
echo -e "\033[0m你必须拥有一份配置文件才能运行服务\033[0m"
echo "-----------------------------------------------"
read -r -p "现在开始导入?(1/0) > " res
[ "$res" = 1 ] && inuserguide=1 && {
. "$CRASHDIR"/menus/6_core_config.sh && set_core_config
inuserguide=""
}
fi
# 回到主界面
echo "-----------------------------------------------"
echo -e "\033[36m很好现在只需要执行启动就可以愉快的使用了\033[0m"
echo "-----------------------------------------------"
read -r -p "立即启动服务?(1/0) > " res
[ "$res" = 1 ] && start_core && sleep 2
return 0
}

File diff suppressed because it is too large Load Diff

3
scripts/starts/README.md Normal file
View File

@@ -0,0 +1,3 @@
用于存放负责启动和服务相关的脚本
此处脚本内容不应包含任何具体中文说明log内容的文字应当从相关lang文件调用

59
scripts/starts/afstart.sh Normal file
View File

@@ -0,0 +1,59 @@
#!/bin/sh
# Copyright (C) Juewuy
#初始化目录
[ -z "$CRASHDIR" ] && CRASHDIR=$( cd $(dirname $0);cd ..;pwd)
. "$CRASHDIR"/libs/get_config.sh
#加载工具
. "$CRASHDIR"/libs/check_cmd.sh
. "$CRASHDIR"/libs/logger.sh
. "$CRASHDIR"/libs/set_cron.sh
#缺省值
[ -z "$firewall_area" ] && firewall_area=1
#延迟启动
[ ! -f "$TMPDIR"/crash_start_time ] && [ -n "$start_delay" ] && [ "$start_delay" -gt 0 ] && {
logger "ShellCrash将延迟$start_delay秒启动" 31
sleep "$start_delay"
}
#设置循环检测面板端口以判定服务启动是否成功
. "$CRASHDIR"/libs/start_wait.sh
if [ -n "$test" -o -n "$(pidof CrashCore)" ]; then
[ "$start_old" = "ON" ] && [ ! -L "$TMPDIR"/CrashCore ] && rm -f "$TMPDIR"/CrashCore #删除缓存目录内核文件
. "$CRASHDIR"/starts/fw_start.sh #配置防火墙流量劫持
date +%s >"$TMPDIR"/crash_start_time #标记启动时间
#TG机器人守护进程
[ "$bot_tg_service" = ON ] && . "$CRASHDIR"/menus/bot_tg_service.sh && bot_tg_cron
#后台还原面板配置
[ -s "$CRASHDIR"/configs/web_save ] && {
. "$CRASHDIR"/libs/web_restore.sh
web_restore >/dev/null 2>&1 &
}
#推送日志
{
sleep 5
logger ShellCrash服务已启动
} &
ckcmd mtd_storage.sh && mtd_storage.sh save >/dev/null 2>&1 & #Padavan保存/etc/storage
#加载定时任务
[ -s "$CRASHDIR"/task/cron ] && croncmd "$CRASHDIR"/task/cron
[ -s "$CRASHDIR"/task/running ] && {
cronset '运行时每'
while read line; do
cronset '2fjdi124dd12s' "$line"
done <"$CRASHDIR"/task/running
}
[ "$start_old" = "ON" ] && cronset '保守模式守护进程' "* * * * * /bin/sh $CRASHDIR/starts/start_legacy_wd.sh shellcrash #ShellCrash保守模式守护进程"
#加载条件任务
[ -s "$CRASHDIR"/task/afstart ] && { . "$CRASHDIR"/task/afstart; } &
[ -s "$CRASHDIR"/task/affirewall -a -s /etc/init.d/firewall -a ! -f /etc/init.d/firewall.bak ] && {
#注入防火墙
line=$(grep -En "fw.* restart" /etc/init.d/firewall | cut -d ":" -f 1)
sed -i.bak "${line}a\\. "$CRASHDIR"/task/affirewall" /etc/init.d/firewall
line=$(grep -En "fw.* start" /etc/init.d/firewall | cut -d ":" -f 1)
sed -i "${line}a\\. $CRASHDIR/task/affirewall" /etc/init.d/firewall
} &
exit 0
else
. "$CRASHDIR"/starts/start_error.sh
"$CRASHDIR"/start.sh stop
fi

147
scripts/starts/bfstart.sh Normal file
View File

@@ -0,0 +1,147 @@
#!/bin/sh
# Copyright (C) Juewuy
#初始化目录
[ -z "$CRASHDIR" ] && CRASHDIR=$( cd $(dirname $0);cd ..;pwd)
. "$CRASHDIR"/libs/get_config.sh
[ -z "$BINDIR" -o -z "$TMPDIR" -o -z "$COMMAND" ] && . "$CRASHDIR"/init.sh >/dev/null 2>&1
[ ! -f "$TMPDIR" ] && mkdir -p "$TMPDIR"
#当上次启动失败时终止自启动
[ -f "CRASHDIR"/.start_error ] && exit 1
#加载工具
. "$CRASHDIR"/libs/check_cmd.sh
. "$CRASHDIR"/libs/check_target.sh
. "$CRASHDIR"/libs/logger.sh
. "$CRASHDIR"/libs/web_get_bin.sh
. "$CRASHDIR"/libs/compare.sh
. "$CRASHDIR"/starts/check_geo.sh
. "$CRASHDIR"/starts/check_core.sh
#缺省值
[ -z "$redir_mod" ] && [ "$USER" = "root" -o "$USER" = "admin" ] && redir_mod='Redir'
[ -z "$dns_mod" ] && dns_mod='redir_host'
[ -z "$redir_mod" ] && firewall_area='4'
routing_mark=$((fwmark + 2))
makehtml() { #生成面板跳转文件
cat >"$BINDIR"/ui/index.html <<EOF
<!DOCTYPE html>
<html lang="en">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ShellCrash面板提示</title>
</head>
<body>
<div style="text-align: center; margin-top: 50px;">
<h1>您还未安装本地面板</h1>
<h3>请在脚本更新功能中(9-4)安装<br>或者使用在线面板:</h3>
<h4>请复制当前地址/ui(不包括)前面的内容填入url位置即可连接</h3>
<a href="http://board.zash.run.place" style="font-size: 24px;">Zashboard面板(推荐)<br></a>
<a style="font-size: 21px;"><br>如已安装请使用Ctrl+F5强制刷新此页面<br></a>
</div>
</body>
</html
EOF
}
catpac() { #生成pac文件
#获取本机host地址
[ -n "$host" ] && host_pac=$host
[ -z "$host_pac" ] && host_pac=$(ubus call network.interface.lan status 2>&1 | grep \"address\" | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
[ -z "$host_pac" ] && host_pac=$(ip a 2>&1 | grep -w 'inet' | grep 'global' | grep -E ' 1(92|0|72)\.' | sed 's/.*inet.//g' | sed 's/\/[0-9][0-9].*$//g' | head -n 1)
cat >"$TMPDIR"/shellcrash_pac <<EOF
function FindProxyForURL(url, host) {
if (
isInNet(host, "0.0.0.0", "255.0.0.0")||
isInNet(host, "10.0.0.0", "255.0.0.0")||
isInNet(host, "127.0.0.0", "255.0.0.0")||
isInNet(host, "224.0.0.0", "224.0.0.0")||
isInNet(host, "240.0.0.0", "240.0.0.0")||
isInNet(host, "172.16.0.0", "255.240.0.0")||
isInNet(host, "192.168.0.0", "255.255.0.0")||
isInNet(host, "169.254.0.0", "255.255.0.0")
)
return "DIRECT";
else
return "PROXY $host_pac:$mix_port; DIRECT; SOCKS5 $host_pac:$mix_port"
}
EOF
compare "$TMPDIR"/shellcrash_pac "$BINDIR"/ui/pac
[ "$?" = 0 ] && rm -rf "$TMPDIR"/shellcrash_pac || mv -f "$TMPDIR"/shellcrash_pac "$BINDIR"/ui/pac
}
#检测网络连接
[ "$network_check" != "OFF" ] && [ ! -f "$TMPDIR"/crash_start_time ] && ckcmd ping && . "$CRASHDIR"/starts/check_network.sh && check_network
[ ! -d "$BINDIR"/ui ] && mkdir -p "$BINDIR"/ui
[ -z "$crashcore" ] && crashcore=meta
#执行条件任务
[ -s "$CRASHDIR"/task/bfstart ] && . "$CRASHDIR"/task/bfstart
#检查内核配置文件
if [ ! -f "$core_config" ]; then
if [ -n "$Url" -o -n "$Https" ]; then
logger "未找到配置文件,正在下载!" 33
. "$CRASHDIR"/starts/core_config.sh && get_core_config
else
logger "未找到配置文件链接,请先导入配置文件!" 31
exit 1
fi
fi
#检查dashboard文件
if [ -f "$CRASHDIR"/ui/CNAME -a ! -f "$BINDIR"/ui/CNAME ]; then
cp -rf "$CRASHDIR"/ui "$BINDIR"
fi
[ ! -s "$BINDIR"/ui/index.html ] && makehtml #如没有面板则创建跳转界面
catpac #生成pac文件
#内核及内核配置文件检查
[ "$CRASHDIR" != "$BINDIR" ] && {
mkdir -p "$BINDIR"/providers
ln -sf "$CRASHDIR"/providers/* "$BINDIR"/providers/
}
if echo "$crashcore" | grep -q 'singbox'; then
. "$CRASHDIR"/starts/singbox_check.sh && singbox_check
[ -d "$TMPDIR"/jsons ] && rm -rf "$TMPDIR"/jsons/* || mkdir -p "$TMPDIR"/jsons #准备目录
if [ "$disoverride" != "1" ];then
. "$CRASHDIR"/starts/singbox_modify.sh && modify_json
else
ln -sf "$core_config" "$TMPDIR"/jsons/config.json
fi
else
. "$CRASHDIR"/starts/clash_check.sh && clash_check
if [ "$disoverride" != "1" ];then
. "$CRASHDIR"/starts/clash_modify.sh && modify_yaml
else
ln -sf "$core_config" "$TMPDIR"/config.yaml
fi
fi
#检查下载cnip绕过相关文件
[ "$cn_ip_route" = "ON" ] && [ "$dns_mod" != "fake-ip" ] && {
[ "$firewall_mod" = nftables ] || ckcmd ipset && {
. "$CRASHDIR"/starts/check_cnip.sh
ck_cn_ipv4
[ "$ipv6_redir" = "ON" ] && ck_cn_ipv6
}
}
#添加shellcrash用户
[ "$firewall_area" = 2 ] || [ "$firewall_area" = 3 ] || [ "$(cat /proc/1/comm)" = "systemd" ] &&
[ -z "$(id shellcrash 2>/dev/null | grep 'root')" ] && {
ckcmd userdel && userdel shellcrash 2>/dev/null
sed -i '/0:7890/d' /etc/passwd
sed -i '/x:7890/d' /etc/group
if ckcmd useradd; then
useradd shellcrash -u 7890
sed -Ei s/7890:7890/0:7890/g /etc/passwd
else
echo "shellcrash:x:0:7890:::" >>/etc/passwd
fi
}
#加载系统内核组件
[ "$redir_mod" = "Tun" -o "$redir_mod" = "Mix" ] && ckcmd modprobe && modprobe tun 2>/dev/null
#清理debug日志
rm -rf /tmp/ShellCrash/debug.log
rm -rf "$CRASHDIR"/debug.log
exit 0

Some files were not shown because too many files have changed in this diff Show More