diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..4163ce8a
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,13 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+
+[*.sh]
+indent_style = space
+indent_size = 4
+shell_variant = posix
+simplify = true
+switch_case_indent = true
+
diff --git a/.github/workflows/bin_update.yml b/.github/workflows/bin_update.yml
index 835fcc2a..a833361c 100644
--- a/.github/workflows/bin_update.yml
+++ b/.github/workflows/bin_update.yml
@@ -17,6 +17,10 @@ jobs:
fetch-depth: 1
persist-credentials: false # 禁用默认凭据(我们用 token push)
+ - name: Fetch master and dev refs
+ run: |
+ git fetch origin master dev
+
- name: Apt Update & Update CA
env:
DEBIAN_FRONTEND: noninteractive
@@ -136,6 +140,12 @@ jobs:
sed -i "s/GeoIP_v=.*/GeoIP_v=$(date '+%Y%m%d')/" version
echo 数据库及根证书文件更新完成!
+ - name: Sync master/dev files into update branch
+ run: |
+ # 只同步文件内容,不带任何 git 状态
+ git archive --format=tar origin/master ShellCrash.tar.gz version | tar -x -C .
+ git archive --format=tar origin/dev install.sh install_en.sh public rules | tar -x -C .
+
- name: Rebuild update branch with no history
run: |
# 彻底删除历史记录
diff --git a/.github/workflows/core_auto_update.yml b/.github/workflows/core_auto_update.yml
index d125f6bb..6f755f5f 100644
--- a/.github/workflows/core_auto_update.yml
+++ b/.github/workflows/core_auto_update.yml
@@ -2,7 +2,7 @@ name: core_auto_update
on:
schedule:
- - cron: 0 18 * * *
+ - cron: 0 18 */3 * *
workflow_dispatch:
jobs:
@@ -12,7 +12,7 @@ jobs:
uses: juewuy/ShellCrash/.github/workflows/update_singbox_core.yaml@dev
with:
tag1: reF1nd/sing-box
- tag2: reF1nd-dev
+ tag2: reF1nd-testing
tag4: singboxr
tag5: with_gvisor,with_quic,with_dhcp,with_wireguard,with_utls,with_shadowsocksr,with_acme,with_clash_api,with_tailscale
tag6: gz
@@ -20,6 +20,7 @@ jobs:
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
diff --git a/.github/workflows/core_easy_update.yaml b/.github/workflows/core_easy_update.yaml
new file mode 100644
index 00000000..0b2f9787
--- /dev/null
+++ b/.github/workflows/core_easy_update.yaml
@@ -0,0 +1,90 @@
+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)
+ [ "${{ inputs.tag1 }}" = singboxr ] && latest_tag="${latest_tag}-reF1nd"
+ 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: no_tailscale
+ 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
+
diff --git a/.github/workflows/update_meta_core.yaml b/.github/workflows/update_meta_core.yaml
index cdca176c..d5a960f0 100644
--- a/.github/workflows/update_meta_core.yaml
+++ b/.github/workflows/update_meta_core.yaml
@@ -64,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}}
@@ -74,7 +74,7 @@ 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
@@ -137,8 +137,8 @@ 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
@@ -188,11 +188,11 @@ jobs:
- name: Zip core by upx
if: env.ZIPTYPE == 'upx'
- run: |
- wget https://github.com/upx/upx/releases/download/v3.96/upx-3.96-amd64_linux.tar.xz
- wget https://github.com/upx/upx/releases/download/v3.94/upx-3.94-amd64_linux.tar.xz
- tar xf upx-3.96-amd64_linux.tar.xz
- tar xf upx-3.94-amd64_linux.tar.xz
+ 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
@@ -201,12 +201,15 @@ jobs:
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-3.9*
+ rm -rf upx-*
- name: Zip core by tar
if: env.ZIPTYPE == 'tar.gz'
@@ -250,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: |
diff --git a/.github/workflows/update_singbox_core.yaml b/.github/workflows/update_singbox_core.yaml
index 06e90836..96b16288 100644
--- a/.github/workflows/update_singbox_core.yaml
+++ b/.github/workflows/update_singbox_core.yaml
@@ -88,7 +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 | sed 's/-reF1nd//')
+ version=$(echo ${version%-*})
echo version=$version >> $GITHUB_OUTPUT
if [ -z "$TAGS" ];then
if [ "$REPO" = 'SagerNet/sing-box' ];then
@@ -208,10 +208,10 @@ jobs:
- name: Zip core by upx
if: env.ZIPTYPE == 'upx'
run: |
- wget https://github.com/upx/upx/releases/download/v3.96/upx-3.96-amd64_linux.tar.xz
- wget https://github.com/upx/upx/releases/download/v3.94/upx-3.94-amd64_linux.tar.xz
- tar xf upx-3.96-amd64_linux.tar.xz
- tar xf upx-3.94-amd64_linux.tar.xz
+ 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
@@ -220,12 +220,15 @@ jobs:
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-3.9*
+ rm -rf upx-*
- name: Zip core by tar
if: env.ZIPTYPE == 'tar.gz'
@@ -256,7 +259,7 @@ jobs:
mkdir -p ./bin/${crashcore}
mv -f ./tmp/singbox-linux-* ./bin/${crashcore}/
rm -fr ./tmp
- [ "${{ inputs.tag6 }}" = tar.gz ] && sed -i "s/${crashcore}_v=.*/${crashcore}_v=${VERSION}/" ./bin/version
+ [ "${{ inputs.tag6 }}" = upx ] && 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
diff --git a/README.md b/README.md
index 20137129..2d0973cf 100644
--- a/README.md
+++ b/README.md
@@ -1,24 +1,178 @@
-
-
ShellCrash
-
-
-
-
+
ShellCrash
+
+
+
+
-[中文](README_CN.md) | English
+
+ A powerful script tool for the convenient deployment and management of mihomo/sing-box kernels in Shell environments.
+
-## Function introduction:
+
+ 简体中文 | English
+
-~Convenient use in Shell environment through management script [Crash](https://github.com/Dreamacro/Crash)
~Support management of [Crash functions](https://lancellc.gitbook.io/Crash)
~Support online import [Crash](https://github.com/Dreamacro/Crash) supports sharing, subscription and configuration links
~Support configuration timing tasks, support configuration file timing updates
~Support online installation and Use local web panel to manage built-in rules
~Support routing mode, native mode and other mode switching
~Support online update
+---
-## Equipment support:
+## :rocket: Core Features
-~Support various router devices based on OpenWrt or secondary custom development using OpenWrt
~Support various devices running standard Linux systems (such as Debian/CenOS/Armbian, etc.)
~Compatible with Padavan firmware (conservative mode), Pandora firmware
~Compatible with various types of devices customized and developed using the Linux kernel
——————————
~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)
+- **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).
diff --git a/README_CN.md b/README_CN.md
index ee23aee0..c0343630 100644
--- a/README_CN.md
+++ b/README_CN.md
@@ -1,10 +1,7 @@
-
-
ShellCrash
-
+ShellCrash
-
-
-
+
+
@@ -12,147 +9,183 @@
-中文 | [English](README.md)
+
+ 一款在 Shell 环境下便捷部署与管理 mihomo/sing-box 内核的脚本工具
+
-功能简介:
---
+
+ 简体中文 | English
+
-~通过管理脚本在Shell环境下便捷使用Mihomo/Singbox内核
-~支持在Shell环境下管理
-~支持在线导入订阅及配置链接
-~支持配置定时任务,支持配置文件定时更新
-~支持在线安装及使用本地网页面板管理内置规则
-~支持路由模式、本机模式等多种模式切换
-~支持在线更新
+---
-设备支持:
---
+## :rocket: 核心特性
-~支持各种基于OpenWrt或使用OpenWrt二次定制开发的路由器设备
-~支持各种运行标准Linux系统(如Debian/CenOS/Armbian等)的设备
-~兼容Padavan固件(保守模式)、潘多拉固件以及华硕/梅林固件
-~兼容各类使用Linux内核定制开发的各类型设备
+- **多内核支持**:在 Shell 环境下便捷管理及切换 **mihomo** 与 **sing-box** 内核。
+- **灵活配置管理**:支持在线导入订阅连结及配置文件,简化配置流程。
+- **自动化任务**:支持配置定时任务,实现配置文件与规则的自动定时更新。
+- **图形化面板**:支持在线安装并使用本地 Web 面板(Dashboard),直观管理内置规则与流量。
+- **多模式运行**:支持路由模式、本机模式等多种流量转发模式切换。
+- **一键维护**:内置脚本在线更新功能,保持版本与功能的及时更迭。
-——————————
-~更多设备支持,请提issue或前往TG群反馈(需提供设备名称及运行uname -a返回的设备核心信息)
+## :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设备可使用自带终端安装)
-~使用SSH连接工具(如putty,JuiceSSH,系统自带终端等)路由器或Linux设备的SSH管理界面或终端界面
+---
-~之后在SSH界面执行目标设备对应的安装命令,并按照后续提示完成安装
+## :hammer_and_wrench: 安装指南
-### 在线安装:
+> [!TIP]
+> 若遇到连接失败或SSL相关问题,请尝试切换至其他安装镜像站。
-(**如无法连接或出现SSL连接错误,请尝试更换各种不同的安装源!**)
+### 前置条件
+1. 确保设备已开启 **SSH** 并获得 **Root 权限**(带图形介面的 Linux 系统可直接使用终端)。
+2. 使用 SSH 工具(如 Putty、JuiceSSH、或系统自带终端)连接至设备。
-~**标准Linux设备安装:**
+### :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 && . /etc/profile &> /dev/null
-```
-或者
-```shell
-sudo -i #切换到root用户,如果需要密码,请输入密码
-export url='https://gh.jwsc.eu.org/master' && bash -c "$(curl -kfsSl $url/install.sh)" && . /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安装**:
+> 或使用 curl 安装(作者私人源)
-```shell
-#GitHub源(可能需要代理)
-export url='https://raw.githubusercontent.com/juewuy/ShellCrash/master' && sh -c "$(curl -kfsSl $url/install.sh)" && . /etc/profile &> /dev/null
-```
-或者
-```shell
-#jsDelivrCDN源
-export url='https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master' && sh -c "$(curl -kfsSl $url/install.sh)" && . /etc/profile &> /dev/null
-```
-或者
-```shell
-#作者私人源
-export url='https://gh.jwsc.eu.org/master' && sh -c "$(curl -kfsSl $url/install.sh)" && . /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安装**:
+### :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 && . /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 && . /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安装**:
+> 或 jsDelivr CDN 源
-```Shell
-#作者私人http内测源
-export url='http://t.jwsc.eu.org' && wget -q -O /tmp/install.sh $url/install.sh && sh /tmp/install.sh && . /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
```
-##### ~**虚拟机安装:**
+> 或作者私人源
+```sh
+export url='https://gh.jwsc.eu.org/master' \
+ && sh -c "$(curl -kfsSl $url/install.sh)" \
+ && . /etc/profile &> /dev/null
+```
-虚拟机环境强烈建议使用Alpine镜像安装
+**使用 `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 && . /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安装:
+ ### :whale: Docker
-请前往[ShellCrash官方Docker镜像](https://hub.docker.com/r/juewuy/shellcrash)
+ 请访问官方 Docker 镜像:
-### **本地安装:**
+- [ShellCrash on Docker Hub](https://hub.docker.com/r/juewuy/shellcrash)
-如使用在线安装出现问题,请参考:[本地安装ShellCrash的教程 | Juewuy's Blog](https://juewuy.github.io/bdaz) 使用本地安装!
-### 使用脚本:
+### :package: 本地安装
-安装完成管理脚本后,执行如下命令使用~
+若无法进行在线安装,请参照以下指南执行本地安装:
-```Shell
-crash #进入对话
-crash -h #帮助列表
-```
+- [本地安装ShellCrash教程 | Juewuy's Blog](https://juewuy.github.io/bdaz)
-#### **运行时的额外依赖**:
+---
-> 大部分的设备/系统都已经预装了以下的大部分依赖,使用时如无影响可以无视之
+## :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)
+---
-#### [大米-群友力荐,流媒体解锁,月付推荐](https://1s.bigmeok.me/user#/register?code=2PuWY9I7)
+## :airplane: 机场推荐
+
+- [**大米**](https://1s.bigmeok.me/user#/register?code=2PuWY9I7),群友力荐,流媒体解锁,月付推荐。
diff --git a/ShellCrash.tar.gz b/ShellCrash.tar.gz
index a66de7e0..77e93bd1 100644
Binary files a/ShellCrash.tar.gz and b/ShellCrash.tar.gz differ
diff --git a/bin/version b/bin/version
index db0d825b..e40a355d 100644
--- a/bin/version
+++ b/bin/version
@@ -1,4 +1,4 @@
meta_v=v1.19.17
singboxr_v=1.13.0-alpha.27
-versionsh=1.9.4release
+versionsh=1.9.5beta1
GeoIP_v=20251205
diff --git a/install.sh b/install.sh
index d8dc188c..b5eff7cb 100644
--- a/install.sh
+++ b/install.sh
@@ -1,23 +1,25 @@
-#!/usr/bin/env 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 "***********************************************"
-# Check available capacity
-dir_avail() {
- df -h >/dev/null 2>&1 && h="$2"
- df -P $h "${1:-.}" 2>/dev/null | awk 'NR==2 {print $4}'
-}
+language=chs
+[ -z "$url" ] && url="https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master"
-ckcmd() { #检查命令
- if command -v sh >/dev/null 2>&1;then
+# 内置工具
+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
@@ -29,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
@@ -40,296 +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 ;;
- 0) echo "安装已取消"; exit 1 ;;
- *) 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
diff --git a/install_en.sh b/install_en.sh
new file mode 100644
index 00000000..ea6a24a8
--- /dev/null
+++ b/install_en.sh
@@ -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
diff --git a/public/fallback_filter.list b/public/fallback_filter.list
deleted file mode 100644
index f6048b18..00000000
--- a/public/fallback_filter.list
+++ /dev/null
@@ -1,2 +0,0 @@
-+.bing.com
-+.linkedin.com
diff --git a/public/servers.list b/public/servers.list
index 90811fa5..a88c41b3 100644
--- a/public/servers.list
+++ b/public/servers.list
@@ -29,4 +29,4 @@
516 DustinWin黑名单模式规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Blacklist.ini
517 DustinWin无广告黑名单模式规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Blacklist_NoAds.ini
518 DustinWin轻量规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Light.ini
-519 DustinWin极简规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Nano.ini
+519 DustinWin极简规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Nano.ini
\ No newline at end of file
diff --git a/public/servers_chs.list b/public/servers_chs.list
new file mode 100644
index 00000000..90811fa5
--- /dev/null
+++ b/public/servers_chs.list
@@ -0,0 +1,32 @@
+# ID&类型 说明 地址 其他说明 (类型:100-三版全通源;200-单一源;300-基础sub;400-meta_sub;500-规则地址)
+
+101 Jsdelivr_CDN源 https://cdn.jsdelivr.net/gh/juewuy/ShellCrash
+102 Github直连源(请注意网络环境) https://raw.githubusercontent.com/juewuy/ShellCrash
+103 ShellClash自建源(请勿滥用!) https://gh.jwsc.eu.org
+104 Cloudflare_CDN源(推荐) https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash
+
+202 http私人内测源(危险!非必要请勿使用) http://t.jwsc.eu.org 开发版
+
+401 作者提供,支持vless|hy2 https://sub.jwsc.eu.org ua
+402 肥羊提供(有广告),支持vless|hy2 https://api.v1.mk diyua
+403 肥羊提供(有广告),支持vless|hy2 https://url.v1.mk diyua
+
+501 Acl4SSR全能优化版 https://github.com/juewuy/ShellCrash/raw/dev/rules/ShellClash.ini (推荐)
+502 Acl4SSR精简优化版 https://github.com/juewuy/ShellCrash/raw/dev/rules/ShellClash_Mini.ini (推荐)
+503 Acl4SSR全能优化+去广告增强 https://github.com/juewuy/ShellCrash/raw/dev/rules/ShellClash_Block.ini
+504 Acl4SSR极简版 https://github.com/juewuy/ShellCrash/raw/dev/rules/ShellClash_Nano.ini (适合自建节点)
+505 Acl4SSR分流&游戏增强 https://github.com/juewuy/ShellCrash/raw/dev/rules/ShellClash_Full.ini
+506 Acl4SSR分流&游戏&去广告增强 https://github.com/juewuy/ShellCrash/raw/dev/rules/ShellClash_Full_Block.ini (低性能设备慎用)
+507 洞主规则精简版 https://github.com/juewuy/ShellCrash/raw/dev/rules/lhie1_clash.ini
+508 洞主规则重度完整版 https://github.com/juewuy/ShellCrash/raw/dev/rules/lhie1_dler.ini
+509 Acl4SSR多国精简 https://github.com/juewuy/ShellCrash/raw/dev/rules/ACL4SSR_Online_Mini_MultiCountry.ini
+510 Acl4SSR回国专用 https://github.com/juewuy/ShellCrash/raw/dev/rules/ACL4SSR_BackCN.ini
+511 Acl4SSR增强国外GFW https://github.com/juewuy/ShellCrash/raw/dev/rules/ACL4SSR_WithGFW.ini (适合黑名单模式使用)
+512 DustinWin全分组规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Full.ini
+513 DustinWin无广告全分组规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Full_NoAds.ini
+514 DustinWin精简规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Lite.ini (推荐)
+515 DustinWin无广告精简规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Lite_NoAds.ini
+516 DustinWin黑名单模式规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Blacklist.ini
+517 DustinWin无广告黑名单模式规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Blacklist_NoAds.ini
+518 DustinWin轻量规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Light.ini
+519 DustinWin极简规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Nano.ini
diff --git a/public/servers_en.list b/public/servers_en.list
new file mode 100644
index 00000000..fa46d5e6
--- /dev/null
+++ b/public/servers_en.list
@@ -0,0 +1,30 @@
+# ID&类型 说明 地址 其他说明 (类型:100-三版全通源;200-单一源;300-基础sub;400-meta_sub;500-规则地址)
+
+101 Jsdelivr_CDN https://cdn.jsdelivr.net/gh/juewuy/ShellCrash
+102 Github https://raw.githubusercontent.com/juewuy/ShellCrash
+103 ShellClash https://gh.jwsc.eu.org
+104 Cloudflare https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash
+
+401 ... https://sub.jwsc.eu.org ua
+402 ... https://api.v1.mk diyua
+403 ... https://url.v1.mk diyua
+
+501 Acl4SSR全能优化版 https://github.com/juewuy/ShellCrash/raw/dev/rules/ShellClash.ini (推荐)
+502 Acl4SSR精简优化版 https://github.com/juewuy/ShellCrash/raw/dev/rules/ShellClash_Mini.ini (推荐)
+503 Acl4SSR全能优化+去广告增强 https://github.com/juewuy/ShellCrash/raw/dev/rules/ShellClash_Block.ini
+504 Acl4SSR极简版 https://github.com/juewuy/ShellCrash/raw/dev/rules/ShellClash_Nano.ini (适合自建节点)
+505 Acl4SSR分流&游戏增强 https://github.com/juewuy/ShellCrash/raw/dev/rules/ShellClash_Full.ini
+506 Acl4SSR分流&游戏&去广告增强 https://github.com/juewuy/ShellCrash/raw/dev/rules/ShellClash_Full_Block.ini (低性能设备慎用)
+507 洞主规则精简版 https://github.com/juewuy/ShellCrash/raw/dev/rules/lhie1_clash.ini
+508 洞主规则重度完整版 https://github.com/juewuy/ShellCrash/raw/dev/rules/lhie1_dler.ini
+509 Acl4SSR多国精简 https://github.com/juewuy/ShellCrash/raw/dev/rules/ACL4SSR_Online_Mini_MultiCountry.ini
+510 Acl4SSR回国专用 https://github.com/juewuy/ShellCrash/raw/dev/rules/ACL4SSR_BackCN.ini
+511 Acl4SSR增强国外GFW https://github.com/juewuy/ShellCrash/raw/dev/rules/ACL4SSR_WithGFW.ini (适合黑名单模式使用)
+512 DustinWin全分组规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Full.ini
+513 DustinWin无广告全分组规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Full_NoAds.ini
+514 DustinWin精简规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Lite.ini (推荐)
+515 DustinWin无广告精简规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Lite_NoAds.ini
+516 DustinWin黑名单模式规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Blacklist.ini
+517 DustinWin无广告黑名单模式规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Blacklist_NoAds.ini
+518 DustinWin轻量规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Light.ini
+519 DustinWin极简规则 https://raw.githubusercontent.com/DustinWin/ruleset_geodata/master/rule_templates/DustinWin_Nano.ini
diff --git a/public/task.list b/public/task_chs.list
similarity index 100%
rename from public/task.list
rename to public/task_chs.list
diff --git a/public/task_en.list b/public/task_en.list
new file mode 100644
index 00000000..c9ba3429
--- /dev/null
+++ b/public/task_en.list
@@ -0,0 +1,19 @@
+#TaskID#TaskCommand#TaskDescription (use # as separator; # is not allowed in command or description)
+
+101#$CRASHDIR/start.sh start#Start ShellCrash
+102#$CRASHDIR/start.sh stop#Stop ShellCrash service
+103#$CRASHDIR/start.sh restart#Restart ShellCrash service
+104#$CRASHDIR/task/task.sh update_config#Update online subscriptions and restart service
+105#$CRASHDIR/task/task.sh hotupdate#Hot update online subscriptions (without restart)
+106#$CRASHDIR/task/task.sh web_save_auto#Automatically save panel configuration
+107#$CRASHDIR/task/task.sh ntp#Automatically sync NTP time
+
+111#$CRASHDIR/task/task.sh update_core#Automatically update core
+112#$CRASHDIR/task/task.sh update_scripts#Automatically update scripts
+113#$CRASHDIR/task/task.sh update_mmdb#Automatically update database files
+
+121#$CRASHDIR/task/task.sh reset_firewall#Reset transparent routing firewall
+122#sleep 70 && touch /etc/banner && reboot#Reboot router device – use with caution
+
+
+
diff --git a/rules/clash_providers/DustinWin_Geo_Full.yaml b/rules/clash_providers/DustinWin_Geo_Full.yaml
index 335f4e3e..4c732b93 100644
--- a/rules/clash_providers/DustinWin_Geo_Full.yaml
+++ b/rules/clash_providers/DustinWin_Geo_Full.yaml
@@ -1,25 +1,24 @@
#DustinWin-geosite全分组规则+去广告
proxy-groups:
- {name: 🚀 节点选择, type: select, proxies: [♻️ 自动选择, 👉 手动选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 📈 网络测试, type: select, proxies: [🎯 全球直连, 🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 🤖 AI 平台, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点]}
- - {name: 📋 Trackerslist, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🎮 游戏服务, type: select, proxies: [🎯 全球直连, 👑 高级节点, 🚀 节点选择]}
- - {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: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🀄️ 直连 IP, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🧱 代理域名, type: select, proxies: [🚀 节点选择, 🎯 全球直连]}
+ - {name: 📈 网络测试, type: select, proxies: [🎯 本地直连, 🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🕹️ 游戏平台, type: select, proxies: [🚀 节点选择, 👑 高级节点, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🤖 AI 平台, type: select, proxies: [🚀 节点选择, 👑 高级节点, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🎮 游戏服务, type: select, proxies: [🎯 本地直连, 👑 高级节点, 🚀 节点选择]}
+ - {name: 🪟 微软服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🇬 谷歌服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🍎 苹果服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🌍 国外媒体, type: select, proxies: [🚀 节点选择, 👑 高级节点, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🇨🇳 国内域名, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🀄️ 国内 IP, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🌎 国外域名, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 📲 电报消息, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 🔒 私有网络, type: select, proxies: [🎯 全球直连], hidden: true}
- - {name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}, 🎯 全球直连]}
+ - {name: 🔒 私有网络, type: select, proxies: [🎯 本地直连], hidden: true}
+ - {name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}, 🎯 本地直连]}
- {name: 🛑 广告域名, type: select, proxies: [🔴 全球拦截, 🟢 全球绕过]}
- {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: [DIRECT], hidden: true}
- {name: 👑 高级节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(专线|专用|高级|直连|急速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)"}
- {name: 📉 省流节点, type: url-test, tolerance: 100, include-all: true, filter: "(0\\.[1-5]|低倍率|省流|大流量)"}
@@ -34,20 +33,18 @@ proxy-groups:
rules:
- GEOSITE,private,🔒 私有网络
- GEOSITE,ads,🛑 广告域名
- - GEOSITE,trackerslist,📋 Trackerslist
- GEOSITE,microsoft-cn,🪟 微软服务
- GEOSITE,apple-cn,🍎 苹果服务
- GEOSITE,google-cn,🇬 谷歌服务
- GEOSITE,games-cn,🎮 游戏服务
+ - GEOSITE,games,🕹️ 游戏平台
- GEOSITE,media,🌍 国外媒体
- - GEOSITE,games,🎮 游戏平台
- GEOSITE,ai,🤖 AI 平台
- GEOSITE,networktest,📈 网络测试
- - GEOSITE,proxy,🧱 代理域名
- - GEOSITE,cn,🛡️ 直连域名
+ - GEOSITE,proxy,🌎 国外域名
+ - GEOSITE,cn,🇨🇳 国内域名
- GEOIP,private,🔒 私有网络,no-resolve
- - GEOIP,cn,🀄️ 直连 IP
- - GEOIP,media,🌍 国外媒体
- - GEOIP,games,🎮 游戏平台
+ - GEOIP,cn,🀄️ 国内 IP
- GEOIP,telegram,📲 电报消息,no-resolve
+ - GEOIP,media,🌍 国外媒体
- MATCH,🐟 漏网之鱼
\ No newline at end of file
diff --git a/rules/clash_providers/DustinWin_Geo_Full_NoAds.yaml b/rules/clash_providers/DustinWin_Geo_Full_NoAds.yaml
index 31d22fcd..d214e921 100644
--- a/rules/clash_providers/DustinWin_Geo_Full_NoAds.yaml
+++ b/rules/clash_providers/DustinWin_Geo_Full_NoAds.yaml
@@ -1,22 +1,21 @@
#DustinWin-geosite全分组规则
proxy-groups:
- {name: 🚀 节点选择, type: select, proxies: [♻️ 自动选择, 👉 手动选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 📈 网络测试, type: select, proxies: [🎯 全球直连, 🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 🤖 AI 平台, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点]}
- - {name: 📋 Trackerslist, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🎮 游戏服务, type: select, proxies: [🎯 全球直连, 👑 高级节点, 🚀 节点选择]}
- - {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: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🀄️ 直连 IP, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🧱 代理域名, type: select, proxies: [🚀 节点选择, 🎯 全球直连]}
+ - {name: 📈 网络测试, type: select, proxies: [🎯 本地直连, 🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🕹️ 游戏平台, type: select, proxies: [🚀 节点选择, 👑 高级节点, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🤖 AI 平台, type: select, proxies: [🚀 节点选择, 👑 高级节点, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🎮 游戏服务, type: select, proxies: [🎯 本地直连, 👑 高级节点, 🚀 节点选择]}
+ - {name: 🪟 微软服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🇬 谷歌服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🍎 苹果服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🌍 国外媒体, type: select, proxies: [🚀 节点选择, 👑 高级节点, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🇨🇳 国内域名, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🀄️ 国内 IP, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🌎 国外域名, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 📲 电报消息, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 🔒 私有网络, type: select, proxies: [🎯 全球直连], hidden: true}
- - {name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}, 🎯 全球直连]}
- - {name: 🎯 全球直连, type: select, proxies: [DIRECT], hidden: true}
+ - {name: 🔒 私有网络, type: select, proxies: [🎯 本地直连], hidden: true}
+ - {name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}, 🎯 本地直连]}
+ - {name: 🎯 本地直连, type: select, proxies: [DIRECT], hidden: true}
- {name: 👑 高级节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(专线|专用|高级|直连|急速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)"}
- {name: 📉 省流节点, type: url-test, tolerance: 100, include-all: true, filter: "(0\\.[1-5]|低倍率|省流|大流量)"}
@@ -30,20 +29,18 @@ proxy-groups:
rules:
- GEOSITE,private,🔒 私有网络
- - GEOSITE,trackerslist,📋 Trackerslist
- GEOSITE,microsoft-cn,🪟 微软服务
- GEOSITE,apple-cn,🍎 苹果服务
- GEOSITE,google-cn,🇬 谷歌服务
- GEOSITE,games-cn,🎮 游戏服务
+ - GEOSITE,games,🕹️ 游戏平台
- GEOSITE,media,🌍 国外媒体
- - GEOSITE,games,🎮 游戏平台
- GEOSITE,ai,🤖 AI 平台
- GEOSITE,networktest,📈 网络测试
- - GEOSITE,proxy,🧱 代理域名
- - GEOSITE,cn,🛡️ 直连域名
+ - GEOSITE,proxy,🌎 国外域名
+ - GEOSITE,cn,🇨🇳 国内域名
- GEOIP,private,🔒 私有网络,no-resolve
- - GEOIP,cn,🀄️ 直连 IP
- - GEOIP,media,🌍 国外媒体
- - GEOIP,games,🎮 游戏平台
+ - GEOIP,cn,🀄️ 国内 IP
- GEOIP,telegram,📲 电报消息,no-resolve
+ - GEOIP,media,🌍 国外媒体
- MATCH,🐟 漏网之鱼
\ No newline at end of file
diff --git a/rules/clash_providers/DustinWin_Geo_Light.yaml b/rules/clash_providers/DustinWin_Geo_Light.yaml
index 25356e5d..03f382c3 100644
--- a/rules/clash_providers/DustinWin_Geo_Light.yaml
+++ b/rules/clash_providers/DustinWin_Geo_Light.yaml
@@ -1,12 +1,12 @@
#DustinWin-gesite轻量规则
proxy-groups:
- {name: 🚀 节点选择, type: select, proxies: [♻️ 自动选择, 👉 手动选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 🀄️ 直连 IP, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🧱 代理域名, type: select, proxies: [🚀 节点选择, 🎯 全球直连]}
+ - {name: 🀄️ 国内 IP, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🌎 国外域名, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 📲 电报消息, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 🔒 私有网络, type: select, proxies: [全球直连], hidden: true}
- - {name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}, 🎯 全球直连]}
- - {name: 🎯 全球直连, type: select, proxies: [DIRECT], hidden: true}
+ - {name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}, 🎯 本地直连]}
+ - {name: 🎯 本地直连, type: select, proxies: [DIRECT], hidden: true}
- {name: 👑 高级节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(专线|专用|高级|直连|急速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)"}
- {name: 📉 省流节点, type: url-test, tolerance: 100, include-all: true, filter: "(0\\.[1-5]|低倍率|省流|大流量)"}
@@ -20,9 +20,9 @@ proxy-groups:
rules:
- GEOSITE,private,🔒 私有网络
- - GEOSITE,tld-proxy,🧱 代理域名
- - GEOSITE,proxy,🧱 代理域名
+ - GEOSITE,tld-proxy,🌎 国外域名
+ - GEOSITE,proxy,🌎 国外域名
- GEOIP,private,🔒 私有网络,no-resolve
- - GEOIP,cn,🀄️ 直连 IP
+ - GEOIP,cn,🀄️ 国内 IP
- GEOIP,telegram,📲 电报消息,no-resolve
- MATCH,🐟 漏网之鱼
\ No newline at end of file
diff --git a/rules/clash_providers/DustinWin_Geo_Lite.yaml b/rules/clash_providers/DustinWin_Geo_Lite.yaml
index 9bc12d94..fd1a8764 100644
--- a/rules/clash_providers/DustinWin_Geo_Lite.yaml
+++ b/rules/clash_providers/DustinWin_Geo_Lite.yaml
@@ -1,23 +1,22 @@
#DustinWin-geosite标准规则+去广告
proxy-groups:
- {name: 🚀 节点选择, type: select, proxies: [♻️ 自动选择, 👉 手动选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 📈 网络测试, type: select, proxies: [🎯 全球直连, 🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 🤖 AI 平台, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点]}
- - {name: 📋 Trackerslist, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🎮 游戏服务, type: select, proxies: [🎯 全球直连, 👑 高级节点, 🚀 节点选择]}
- - {name: 🪟 微软服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🇬 谷歌服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🍎 苹果服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🛡️ 直连域名, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🀄️ 直连 IP, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🧱 代理域名, type: select, proxies: [🚀 节点选择, 🎯 全球直连]}
+ - {name: 📈 网络测试, type: select, proxies: [🎯 本地直连, 🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🤖 AI 平台, type: select, proxies: [🚀 节点选择, 👑 高级节点, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🎮 游戏服务, type: select, proxies: [🎯 本地直连, 👑 高级节点, 🚀 节点选择]}
+ - {name: 🪟 微软服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🇬 谷歌服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🍎 苹果服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🇨🇳 国内域名, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🀄️ 国内 IP, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🌎 国外域名, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 📲 电报消息, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 🔒 私有网络, type: select, proxies: [🎯 全球直连], hidden: true}
- - {name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}, 🎯 全球直连]}
+ - {name: 🔒 私有网络, type: select, proxies: [🎯 本地直连], hidden: true}
+ - {name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}, 🎯 本地直连]}
- {name: 🛑 广告域名, type: select, proxies: [🔴 全球拦截, 🟢 全球绕过]}
- {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: [DIRECT], hidden: true}
- {name: 👑 高级节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(专线|专用|高级|直连|急速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)"}
- {name: 📉 省流节点, type: url-test, tolerance: 100, include-all: true, filter: "(0\\.[1-5]|低倍率|省流|大流量)"}
@@ -32,16 +31,15 @@ proxy-groups:
rules:
- GEOSITE,private,🔒 私有网络
- GEOSITE,ads,🛑 广告域名
- - GEOSITE,trackerslist,📋 Trackerslist
- GEOSITE,microsoft-cn,🪟 微软服务
- GEOSITE,apple-cn,🍎 苹果服务
- GEOSITE,google-cn,🇬 谷歌服务
- GEOSITE,games-cn,🎮 游戏服务
- GEOSITE,ai,🤖 AI 平台
- GEOSITE,networktest,📈 网络测试
- - GEOSITE,proxy,🧱 代理域名
- - GEOSITE,cn,🛡️ 直连域名
+ - GEOSITE,proxy,🌎 国外域名
+ - GEOSITE,cn,🇨🇳 国内域名
- GEOIP,private,🔒 私有网络,no-resolve
- - GEOIP,cn,🀄️ 直连 IP
+ - GEOIP,cn,🀄️ 国内 IP
- GEOIP,telegram,📲 电报消息,no-resolve
- MATCH,🐟 漏网之鱼
\ No newline at end of file
diff --git a/rules/clash_providers/DustinWin_Geo_Lite_NoAds.yaml b/rules/clash_providers/DustinWin_Geo_Lite_NoAds.yaml
index 02cdc383..5895d6ea 100644
--- a/rules/clash_providers/DustinWin_Geo_Lite_NoAds.yaml
+++ b/rules/clash_providers/DustinWin_Geo_Lite_NoAds.yaml
@@ -1,20 +1,19 @@
#DustinWin-geosite标准规则
proxy-groups:
- {name: 🚀 节点选择, type: select, proxies: [♻️ 自动选择, 👉 手动选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 📈 网络测试, type: select, proxies: [🎯 全球直连, 🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 🤖 AI 平台, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点]}
- - {name: 📋 Trackerslist, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🎮 游戏服务, type: select, proxies: [🎯 全球直连, 👑 高级节点, 🚀 节点选择]}
- - {name: 🪟 微软服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🇬 谷歌服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🍎 苹果服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🛡️ 直连域名, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🀄️ 直连 IP, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🧱 代理域名, type: select, proxies: [🚀 节点选择, 🎯 全球直连]}
+ - {name: 📈 网络测试, type: select, proxies: [🎯 本地直连, 🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🤖 AI 平台, type: select, proxies: [🚀 节点选择, 👑 高级节点, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🎮 游戏服务, type: select, proxies: [🎯 本地直连, 👑 高级节点, 🚀 节点选择]}
+ - {name: 🪟 微软服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🇬 谷歌服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🍎 苹果服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🇨🇳 国内域名, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🀄️ 国内 IP, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🌎 国外域名, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 📲 电报消息, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 🔒 私有网络, type: select, proxies: [🎯 全球直连], hidden: true}
- - {name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}, 🎯 全球直连]}
- - {name: 🎯 全球直连, type: select, proxies: [DIRECT], hidden: true}
+ - {name: 🔒 私有网络, type: select, proxies: [🎯 本地直连], hidden: true}
+ - {name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}, 🎯 本地直连]}
+ - {name: 🎯 本地直连, type: select, proxies: [DIRECT], hidden: true}
- {name: 👑 高级节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(专线|专用|高级|直连|急速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)"}
- {name: 📉 省流节点, type: url-test, tolerance: 100, include-all: true, filter: "(0\\.[1-5]|低倍率|省流|大流量)"}
@@ -28,16 +27,15 @@ proxy-groups:
rules:
- GEOSITE,private,🔒 私有网络
- - GEOSITE,trackerslist,📋 Trackerslist
- GEOSITE,microsoft-cn,🪟 微软服务
- GEOSITE,apple-cn,🍎 苹果服务
- GEOSITE,google-cn,🇬 谷歌服务
- GEOSITE,games-cn,🎮 游戏服务
- GEOSITE,ai,🤖 AI 平台
- GEOSITE,networktest,📈 网络测试
- - GEOSITE,proxy,🧱 代理域名
- - GEOSITE,cn,🛡️ 直连域名
+ - GEOSITE,proxy,🌎 国外域名
+ - GEOSITE,cn,🇨🇳 国内域名
- GEOIP,private,🔒 私有网络,no-resolve
- - GEOIP,cn,🀄️ 直连 IP
+ - GEOIP,cn,🀄️ 国内 IP
- GEOIP,telegram,📲 电报消息,no-resolve
- MATCH,🐟 漏网之鱼
\ No newline at end of file
diff --git a/rules/clash_providers/DustinWin_RS_Full.yaml b/rules/clash_providers/DustinWin_RS_Full.yaml
index 716e1c46..0ecb34c1 100644
--- a/rules/clash_providers/DustinWin_RS_Full.yaml
+++ b/rules/clash_providers/DustinWin_RS_Full.yaml
@@ -1,25 +1,26 @@
#DustinWin-ruleset全分组规则+去广告
proxy-groups:
- {name: 🚀 节点选择, type: select, proxies: [♻️ 自动选择, 👉 手动选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 📈 网络测试, type: select, proxies: [🎯 全球直连, 🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 🤖 AI 平台, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点]}
- - {name: 📋 Trackerslist, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🎮 游戏服务, type: select, proxies: [🎯 全球直连, 👑 高级节点, 🚀 节点选择]}
- - {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: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🀄️ 直连 IP, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🧱 代理域名, type: select, proxies: [🚀 节点选择, 🎯 全球直连]}
+ - {name: 📈 网络测试, type: select, proxies: [🎯 本地直连, 🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🕹️ 游戏平台, type: select, proxies: [🚀 节点选择, 👑 高级节点, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🤖 AI 平台, type: select, proxies: [🚀 节点选择, 👑 高级节点, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🎮 游戏服务, type: select, proxies: [🎯 本地直连, 👑 高级节点, 🚀 节点选择]}
+ - {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: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🀄️ 国内 IP, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🌎 国外域名, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 📲 电报消息, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 🔒 私有网络, type: select, proxies: [🎯 全球直连], hidden: true}
- - {name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}, 🎯 全球直连]}
+ - {name: 🔒 私有网络, type: select, proxies: [🎯 本地直连], hidden: true}
+ - {name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}, 🎯 本地直连]}
- {name: 🛑 广告域名, type: select, proxies: [🔴 全球拦截, 🟢 全球绕过]}
- {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: [DIRECT], hidden: true}
- {name: 👑 高级节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(专线|专用|高级|直连|急速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)"}
- {name: 📉 省流节点, type: url-test, tolerance: 100, include-all: true, filter: "(0\\.[1-5]|低倍率|省流|大流量)"}
@@ -32,28 +33,20 @@ proxy-groups:
- {name: 🇺🇸 美国节点, type: url-test, tolerance: 100, include-all: true, filter: "(?i)(🇺🇸|美|us|unitedstates|united states)"}
rule-providers:
- private:
- type: http
- behavior: domain
- format: mrs
- path: ./ruleset/private.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/private.mrs"
- interval: 86400
-
ads:
type: http
behavior: domain
format: mrs
path: ./ruleset/ads.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/ads.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/ads.mrs"
interval: 86400
- trackerslist:
+ private:
type: http
behavior: domain
format: mrs
- path: ./ruleset/trackerslist.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/trackerslist.mrs"
+ path: ./ruleset/private.mrs
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/private.mrs"
interval: 86400
microsoft-cn:
@@ -61,7 +54,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/microsoft-cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/microsoft-cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/microsoft-cn.mrs"
interval: 86400
apple-cn:
@@ -69,7 +62,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/apple-cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/apple-cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/apple-cn.mrs"
interval: 86400
google-cn:
@@ -77,7 +70,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/google-cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/google-cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/google-cn.mrs"
interval: 86400
games-cn:
@@ -85,15 +78,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/games-cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/games-cn.mrs"
- interval: 86400
-
- media:
- type: http
- behavior: domain
- format: mrs
- path: ./ruleset/media.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/media.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/games-cn.mrs"
interval: 86400
games:
@@ -101,7 +86,31 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/games.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/games.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/games.mrs"
+ interval: 86400
+
+ netflix:
+ type: http
+ behavior: domain
+ format: mrs
+ path: ./ruleset/netflix.mrs
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@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@mihomo-ruleset/youtube.mrs"
+ interval: 86400
+
+ media:
+ type: http
+ behavior: domain
+ format: mrs
+ path: ./ruleset/media.mrs
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/media.mrs"
interval: 86400
ai:
@@ -109,7 +118,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/ai.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/ai.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/ai.mrs"
interval: 86400
networktest:
@@ -117,7 +126,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/networktest.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/networktest.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/networktest.mrs"
interval: 86400
proxy:
@@ -125,7 +134,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/proxy.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/proxy.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/proxy.mrs"
interval: 86400
cn:
@@ -133,7 +142,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/cn.mrs"
interval: 86400
privateip:
@@ -141,7 +150,7 @@ rule-providers:
behavior: ipcidr
format: mrs
path: ./ruleset/privateip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/privateip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/privateip.mrs"
interval: 86400
cnip:
@@ -149,23 +158,7 @@ rule-providers:
behavior: ipcidr
format: mrs
path: ./ruleset/cnip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cnip.mrs"
- interval: 86400
-
- mediaip:
- type: http
- behavior: ipcidr
- format: mrs
- path: ./ruleset/mediaip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/mediaip.mrs"
- interval: 86400
-
- gamesip:
- type: http
- behavior: ipcidr
- format: mrs
- path: ./ruleset/gamesip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/gamesip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/cnip.mrs"
interval: 86400
telegramip:
@@ -173,26 +166,43 @@ rule-providers:
behavior: ipcidr
format: mrs
path: ./ruleset/telegramip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/telegramip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/telegramip.mrs"
+ interval: 86400
+
+ netflixip:
+ type: http
+ behavior: ipcidr
+ format: mrs
+ path: ./ruleset/netflixip.mrs
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/netflixip.mrs"
+ interval: 86400
+
+ mediaip:
+ type: http
+ behavior: ipcidr
+ format: mrs
+ path: ./ruleset/mediaip.mrs
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/mediaip.mrs"
interval: 86400
rules:
- RULE-SET,private,🔒 私有网络
- RULE-SET,ads,🛑 广告域名
- - RULE-SET,trackerslist,📋 Trackerslist
- RULE-SET,microsoft-cn,🪟 微软服务
- RULE-SET,apple-cn,🍎 苹果服务
- RULE-SET,google-cn,🇬 谷歌服务
- RULE-SET,games-cn,🎮 游戏服务
+ - RULE-SET,games,🕹️ 游戏平台
+ - RULE-SET,netflix,🎥 奈飞视频
+ - RULE-SET,youtube,📹 油管视频
- RULE-SET,media,🌍 国外媒体
- - RULE-SET,games,🎮 游戏平台
- RULE-SET,ai,🤖 AI 平台
- RULE-SET,networktest,📈 网络测试
- - RULE-SET,proxy,🧱 代理域名
- - RULE-SET,cn,🛡️ 直连域名
+ - RULE-SET,proxy,🌎 国外域名
+ - RULE-SET,cn,🇨🇳 国内域名
- RULE-SET,privateip,🔒 私有网络,no-resolve
- - RULE-SET,cnip,🀄️ 直连 IP
- - RULE-SET,mediaip,🌍 国外媒体
- - RULE-SET,gamesip,🎮 游戏平台
+ - RULE-SET,cnip,🀄️ 国内 IP
- RULE-SET,telegramip,📲 电报消息,no-resolve
- - MATCH,🐟 漏网之鱼
\ No newline at end of file
+ - RULE-SET,netflixip,🎥 奈飞视频
+ - RULE-SET,mediaip,🌍 国外媒体
+ - MATCH,🐟 漏网之鱼
diff --git a/rules/clash_providers/DustinWin_RS_Full_NoAds.yaml b/rules/clash_providers/DustinWin_RS_Full_NoAds.yaml
index 65b1112a..c5aac943 100644
--- a/rules/clash_providers/DustinWin_RS_Full_NoAds.yaml
+++ b/rules/clash_providers/DustinWin_RS_Full_NoAds.yaml
@@ -1,22 +1,23 @@
#DustinWin-ruleset全分组规则
proxy-groups:
- {name: 🚀 节点选择, type: select, proxies: [♻️ 自动选择, 👉 手动选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 📈 网络测试, type: select, proxies: [🎯 全球直连, 🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 🤖 AI 平台, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点]}
- - {name: 📋 Trackerslist, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {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: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🛡️ 直连域名, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🀄️ 直连 IP, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🧱 代理域名, type: select, proxies: [🚀 节点选择, 🎯 全球直连]}
+ - {name: 📈 网络测试, type: select, proxies: [🎯 本地直连, 🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🕹️ 游戏平台, type: select, proxies: [🚀 节点选择, 👑 高级节点, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🤖 AI 平台, type: select, proxies: [🚀 节点选择, 👑 高级节点, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🎮 游戏服务, type: select, proxies: [🎯 本地直连, 👑 高级节点, 🚀 节点选择]}
+ - {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: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🀄️ 国内 IP, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🌎 国外域名, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 📲 电报消息, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 🔒 私有网络, type: select, proxies: [🎯 全球直连], hidden: true}
- - {name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}, 🎯 全球直连]}
- - {name: 🎯 全球直连, type: select, proxies: [DIRECT], hidden: true}
+ - {name: 🔒 私有网络, type: select, proxies: [🎯 本地直连], hidden: true}
+ - {name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}, 🎯 本地直连]}
+ - {name: 🎯 本地直连, type: select, proxies: [DIRECT], hidden: true}
- {name: 👑 高级节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(专线|专用|高级|直连|急速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)"}
- {name: 📉 省流节点, type: url-test, tolerance: 100, include-all: true, filter: "(0\\.[1-5]|低倍率|省流|大流量)"}
@@ -34,15 +35,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/private.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/private.mrs"
- interval: 86400
-
- trackerslist:
- type: http
- behavior: domain
- format: mrs
- path: ./ruleset/trackerslist.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/trackerslist.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/private.mrs"
interval: 86400
microsoft-cn:
@@ -50,7 +43,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/microsoft-cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/microsoft-cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/microsoft-cn.mrs"
interval: 86400
apple-cn:
@@ -58,7 +51,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/apple-cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/apple-cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/apple-cn.mrs"
interval: 86400
google-cn:
@@ -66,7 +59,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/google-cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/google-cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/google-cn.mrs"
interval: 86400
games-cn:
@@ -74,15 +67,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/games-cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/games-cn.mrs"
- interval: 86400
-
- media:
- type: http
- behavior: domain
- format: mrs
- path: ./ruleset/media.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/media.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/games-cn.mrs"
interval: 86400
games:
@@ -90,7 +75,31 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/games.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/games.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/games.mrs"
+ interval: 86400
+
+ netflix:
+ type: http
+ behavior: domain
+ format: mrs
+ path: ./ruleset/netflix.mrs
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@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@mihomo-ruleset/youtube.mrs"
+ interval: 86400
+
+ media:
+ type: http
+ behavior: domain
+ format: mrs
+ path: ./ruleset/media.mrs
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/media.mrs"
interval: 86400
ai:
@@ -98,7 +107,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/ai.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/ai.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/ai.mrs"
interval: 86400
networktest:
@@ -106,7 +115,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/networktest.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/networktest.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/networktest.mrs"
interval: 86400
proxy:
@@ -114,7 +123,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/proxy.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/proxy.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/proxy.mrs"
interval: 86400
cn:
@@ -122,7 +131,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/cn.mrs"
interval: 86400
privateip:
@@ -130,7 +139,7 @@ rule-providers:
behavior: ipcidr
format: mrs
path: ./ruleset/privateip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/privateip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/privateip.mrs"
interval: 86400
cnip:
@@ -138,23 +147,7 @@ rule-providers:
behavior: ipcidr
format: mrs
path: ./ruleset/cnip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cnip.mrs"
- interval: 86400
-
- mediaip:
- type: http
- behavior: ipcidr
- format: mrs
- path: ./ruleset/mediaip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/mediaip.mrs"
- interval: 86400
-
- gamesip:
- type: http
- behavior: ipcidr
- format: mrs
- path: ./ruleset/gamesip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/gamesip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/cnip.mrs"
interval: 86400
telegramip:
@@ -162,25 +155,42 @@ rule-providers:
behavior: ipcidr
format: mrs
path: ./ruleset/telegramip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/telegramip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/telegramip.mrs"
+ interval: 86400
+
+ netflixip:
+ type: http
+ behavior: ipcidr
+ format: mrs
+ path: ./ruleset/netflixip.mrs
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/netflixip.mrs"
+ interval: 86400
+
+ mediaip:
+ type: http
+ behavior: ipcidr
+ format: mrs
+ path: ./ruleset/mediaip.mrs
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/mediaip.mrs"
interval: 86400
rules:
- RULE-SET,private,🔒 私有网络
- - RULE-SET,trackerslist,📋 Trackerslist
- RULE-SET,microsoft-cn,🪟 微软服务
- RULE-SET,apple-cn,🍎 苹果服务
- RULE-SET,google-cn,🇬 谷歌服务
- RULE-SET,games-cn,🎮 游戏服务
+ - RULE-SET,games,🕹️ 游戏平台
+ - RULE-SET,netflix,🎥 奈飞视频
+ - RULE-SET,youtube,📹 油管视频
- RULE-SET,media,🌍 国外媒体
- - RULE-SET,games,🎮 游戏平台
- RULE-SET,ai,🤖 AI 平台
- RULE-SET,networktest,📈 网络测试
- - RULE-SET,proxy,🧱 代理域名
- - RULE-SET,cn,🛡️ 直连域名
+ - RULE-SET,proxy,🌎 国外域名
+ - RULE-SET,cn,🇨🇳 国内域名
- RULE-SET,privateip,🔒 私有网络,no-resolve
- - RULE-SET,cnip,🀄️ 直连 IP
- - RULE-SET,mediaip,🌍 国外媒体
- - RULE-SET,gamesip,🎮 游戏平台
+ - RULE-SET,cnip,🀄️ 国内 IP
- RULE-SET,telegramip,📲 电报消息,no-resolve
- - MATCH,🐟 漏网之鱼
\ No newline at end of file
+ - RULE-SET,netflixip,🎥 奈飞视频
+ - RULE-SET,mediaip,🌍 国外媒体
+ - MATCH,🐟 漏网之鱼
diff --git a/rules/clash_providers/DustinWin_RS_Light.yaml b/rules/clash_providers/DustinWin_RS_Light.yaml
index 5f735ec2..6f072266 100644
--- a/rules/clash_providers/DustinWin_RS_Light.yaml
+++ b/rules/clash_providers/DustinWin_RS_Light.yaml
@@ -1,10 +1,11 @@
#DustinWin-ruleset轻量规则
proxy-groups:
- {name: 🚀 节点选择, type: select, proxies: [♻️ 自动选择, 👉 手动选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 🎯 全球直连, type: select, proxies: [DIRECT, 🚀 节点选择]}
- - {name: 🧱 代理域名, type: select, proxies: [🚀 节点选择, DIRECT]}
+ - {name: 🀄️ 国内 IP, 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: [DIRECT], hidden: true}
- {name: 👑 高级节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(专线|专用|高级|直连|急速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)"}
- {name: 📉 省流节点, type: url-test, tolerance: 100, include-all: true, filter: "(0\\.[1-5]|低倍率|省流|大流量)"}
@@ -17,20 +18,12 @@ proxy-groups:
- {name: 🇺🇸 美国节点, type: url-test, tolerance: 100, include-all: true, filter: "(?i)(🇺🇸|美|us|unitedstates|united states)"}
rule-providers:
- cn:
- type: http
- behavior: domain
- format: mrs
- path: ./ruleset/cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cn.mrs"
- interval: 86400
-
private:
type: http
behavior: domain
format: mrs
path: ./ruleset/private.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/private.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/private.mrs"
interval: 86400
tld-proxy:
@@ -38,7 +31,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/tld-proxy.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/tld-proxy.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/tld-proxy.mrs"
interval: 86400
proxy:
@@ -46,7 +39,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/proxy.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/proxy.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/proxy.mrs"
interval: 86400
privateip:
@@ -54,7 +47,7 @@ rule-providers:
behavior: ipcidr
format: mrs
path: ./ruleset/privateip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/privateip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/privateip.mrs"
interval: 86400
cnip:
@@ -62,7 +55,7 @@ rule-providers:
behavior: ipcidr
format: mrs
path: ./ruleset/cnip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cnip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/cnip.mrs"
interval: 86400
telegramip:
@@ -70,15 +63,14 @@ rule-providers:
behavior: ipcidr
format: mrs
path: ./ruleset/telegramip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/telegramip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/telegramip.mrs"
interval: 86400
rules:
- RULE-SET,private,DIRECT
- - RULE-SET,tld-proxy,🧱 代理域名
- - RULE-SET,proxy,🧱 代理域名
- - RULE-SET,cn,🎯 全球直连
+ - RULE-SET,tld-proxy,🌎 国外域名
+ - RULE-SET,proxy,🌎 国外域名
- RULE-SET,privateip,DIRECT,no-resolve
- - RULE-SET,cnip,🎯 全球直连
+ - RULE-SET,cnip,🀄️ 国内 IP
- RULE-SET,telegramip,📲 电报消息,no-resolve
- - MATCH,🐟 漏网之鱼
\ No newline at end of file
+ - MATCH,🐟 漏网之鱼
diff --git a/rules/clash_providers/DustinWin_RS_Lite.yaml b/rules/clash_providers/DustinWin_RS_Lite.yaml
index 9439c5cc..068d009a 100644
--- a/rules/clash_providers/DustinWin_RS_Lite.yaml
+++ b/rules/clash_providers/DustinWin_RS_Lite.yaml
@@ -1,23 +1,22 @@
#DustinWin-ruleset标准规则+去广告
proxy-groups:
- {name: 🚀 节点选择, type: select, proxies: [♻️ 自动选择, 👉 手动选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 📈 网络测试, type: select, proxies: [🎯 全球直连, 🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 🤖 AI 平台, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点]}
- - {name: 📋 Trackerslist, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🎮 游戏服务, type: select, proxies: [🎯 全球直连, 👑 高级节点, 🚀 节点选择]}
- - {name: 🪟 微软服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🇬 谷歌服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🍎 苹果服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🛡️ 直连域名, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🀄️ 直连 IP, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🧱 代理域名, type: select, proxies: [🚀 节点选择, 🎯 全球直连]}
+ - {name: 📈 网络测试, type: select, proxies: [🎯 本地直连, 🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🤖 AI 平台, type: select, proxies: [🚀 节点选择, 👑 高级节点, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🎮 游戏服务, type: select, proxies: [🎯 本地直连, 👑 高级节点, 🚀 节点选择]}
+ - {name: 🪟 微软服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🇬 谷歌服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🍎 苹果服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🇨🇳 国内域名, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🀄️ 国内 IP, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🌎 国外域名, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 📲 电报消息, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 🔒 私有网络, type: select, proxies: [🎯 全球直连], hidden: true}
- - {name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}, 🎯 全球直连]}
+ - {name: 🔒 私有网络, type: select, proxies: [🎯 本地直连], hidden: true}
+ - {name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}, 🎯 本地直连]}
- {name: 🛑 广告域名, type: select, proxies: [🔴 全球拦截, 🟢 全球绕过]}
- {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: [DIRECT], hidden: true}
- {name: 👑 高级节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(专线|专用|高级|直连|急速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)"}
- {name: 📉 省流节点, type: url-test, tolerance: 100, include-all: true, filter: "(0\\.[1-5]|低倍率|省流|大流量)"}
@@ -35,7 +34,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/private.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/private.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/private.mrs"
interval: 86400
ads:
@@ -43,15 +42,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/ads.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/ads.mrs"
- interval: 86400
-
- trackerslist:
- type: http
- behavior: domain
- format: mrs
- path: ./ruleset/trackerslist.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/trackerslist.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/ads.mrs"
interval: 86400
microsoft-cn:
@@ -59,7 +50,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/microsoft-cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/microsoft-cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/microsoft-cn.mrs"
interval: 86400
apple-cn:
@@ -67,7 +58,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/apple-cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/apple-cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/apple-cn.mrs"
interval: 86400
google-cn:
@@ -75,7 +66,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/google-cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/google-cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/google-cn.mrs"
interval: 86400
games-cn:
@@ -83,7 +74,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/games-cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/games-cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/games-cn.mrs"
interval: 86400
ai:
@@ -91,7 +82,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/ai.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/ai.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/ai.mrs"
interval: 86400
networktest:
@@ -99,7 +90,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/networktest.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/networktest.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/networktest.mrs"
interval: 86400
proxy:
@@ -107,7 +98,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/proxy.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/proxy.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/proxy.mrs"
interval: 86400
cn:
@@ -115,7 +106,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/cn.mrs"
interval: 86400
privateip:
@@ -123,7 +114,7 @@ rule-providers:
behavior: ipcidr
format: mrs
path: ./ruleset/privateip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/privateip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/privateip.mrs"
interval: 86400
cnip:
@@ -131,7 +122,7 @@ rule-providers:
behavior: ipcidr
format: mrs
path: ./ruleset/cnip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cnip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/cnip.mrs"
interval: 86400
telegramip:
@@ -139,22 +130,21 @@ rule-providers:
behavior: ipcidr
format: mrs
path: ./ruleset/telegramip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/telegramip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/telegramip.mrs"
interval: 86400
rules:
- RULE-SET,private,🔒 私有网络
- RULE-SET,ads,🛑 广告域名
- - RULE-SET,trackerslist,📋 Trackerslist
- RULE-SET,microsoft-cn,🪟 微软服务
- RULE-SET,apple-cn,🍎 苹果服务
- RULE-SET,google-cn,🇬 谷歌服务
- RULE-SET,games-cn,🎮 游戏服务
- RULE-SET,ai,🤖 AI 平台
- RULE-SET,networktest,📈 网络测试
- - RULE-SET,proxy,🧱 代理域名
- - RULE-SET,cn,🛡️ 直连域名
+ - RULE-SET,proxy,🌎 国外域名
+ - RULE-SET,cn,🇨🇳 国内域名
- RULE-SET,privateip,🔒 私有网络,no-resolve
- - RULE-SET,cnip,🀄️ 直连 IP
+ - RULE-SET,cnip,🀄️ 国内 IP
- RULE-SET,telegramip,📲 电报消息,no-resolve
- - MATCH,🐟 漏网之鱼
\ No newline at end of file
+ - MATCH,🐟 漏网之鱼
diff --git a/rules/clash_providers/DustinWin_RS_Lite_NoAds.yaml b/rules/clash_providers/DustinWin_RS_Lite_NoAds.yaml
index c285c555..9ddfbf7c 100644
--- a/rules/clash_providers/DustinWin_RS_Lite_NoAds.yaml
+++ b/rules/clash_providers/DustinWin_RS_Lite_NoAds.yaml
@@ -1,20 +1,19 @@
#DustinWin-ruleset标准规则
proxy-groups:
- {name: 🚀 节点选择, type: select, proxies: [♻️ 自动选择, 👉 手动选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 📈 网络测试, type: select, proxies: [🎯 全球直连, 🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 🤖 AI 平台, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点]}
- - {name: 📋 Trackerslist, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🎮 游戏服务, type: select, proxies: [🎯 全球直连, 👑 高级节点, 🚀 节点选择]}
- - {name: 🪟 微软服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🇬 谷歌服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🍎 苹果服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🛡️ 直连域名, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🀄️ 直连 IP, type: select, proxies: [🎯 全球直连, 🚀 节点选择]}
- - {name: 🧱 代理域名, type: select, proxies: [🚀 节点选择, 🎯 全球直连]}
+ - {name: 📈 网络测试, type: select, proxies: [🎯 本地直连, 🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🤖 AI 平台, type: select, proxies: [🚀 节点选择, 👑 高级节点, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🎮 游戏服务, type: select, proxies: [🎯 本地直连, 👑 高级节点, 🚀 节点选择]}
+ - {name: 🪟 微软服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🇬 谷歌服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🍎 苹果服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🇨🇳 国内域名, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🀄️ 国内 IP, type: select, proxies: [🎯 本地直连, 🚀 节点选择]}
+ - {name: 🌎 国外域名, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- {name: 📲 电报消息, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - {name: 🔒 私有网络, type: select, proxies: [🎯 全球直连], hidden: true}
- - {name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}, 🎯 全球直连]}
- - {name: 🎯 全球直连, type: select, proxies: [DIRECT], hidden: true}
+ - {name: 🔒 私有网络, type: select, proxies: [🎯 本地直连], hidden: true}
+ - {name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇯🇵 日本节点, 🇸🇬 新加坡节点, 🇺🇸 美国节点, 👑 高级节点, 📉 省流节点, {providers_tags}, 🎯 本地直连]}
+ - {name: 🎯 本地直连, type: select, proxies: [DIRECT], hidden: true}
- {name: 👑 高级节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(专线|专用|高级|直连|急速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)"}
- {name: 📉 省流节点, type: url-test, tolerance: 100, include-all: true, filter: "(0\\.[1-5]|低倍率|省流|大流量)"}
@@ -32,15 +31,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/private.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/private.mrs"
- interval: 86400
-
- trackerslist:
- type: http
- behavior: domain
- format: mrs
- path: ./ruleset/trackerslist.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/trackerslist.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/private.mrs"
interval: 86400
microsoft-cn:
@@ -48,7 +39,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/microsoft-cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/microsoft-cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/microsoft-cn.mrs"
interval: 86400
apple-cn:
@@ -56,7 +47,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/apple-cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/apple-cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/apple-cn.mrs"
interval: 86400
google-cn:
@@ -64,7 +55,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/google-cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/google-cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/google-cn.mrs"
interval: 86400
games-cn:
@@ -72,7 +63,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/games-cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/games-cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/games-cn.mrs"
interval: 86400
ai:
@@ -80,7 +71,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/ai.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/ai.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/ai.mrs"
interval: 86400
networktest:
@@ -88,7 +79,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/networktest.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/networktest.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/networktest.mrs"
interval: 86400
proxy:
@@ -96,7 +87,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/proxy.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/proxy.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/proxy.mrs"
interval: 86400
cn:
@@ -104,7 +95,7 @@ rule-providers:
behavior: domain
format: mrs
path: ./ruleset/cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cn-lite.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/cn.mrs"
interval: 86400
privateip:
@@ -112,7 +103,7 @@ rule-providers:
behavior: ipcidr
format: mrs
path: ./ruleset/privateip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/privateip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/privateip.mrs"
interval: 86400
cnip:
@@ -120,7 +111,7 @@ rule-providers:
behavior: ipcidr
format: mrs
path: ./ruleset/cnip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cnip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/cnip.mrs"
interval: 86400
telegramip:
@@ -128,21 +119,20 @@ rule-providers:
behavior: ipcidr
format: mrs
path: ./ruleset/telegramip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/telegramip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/telegramip.mrs"
interval: 86400
rules:
- RULE-SET,private,🔒 私有网络
- - RULE-SET,trackerslist,📋 Trackerslist
- RULE-SET,microsoft-cn,🪟 微软服务
- RULE-SET,apple-cn,🍎 苹果服务
- RULE-SET,google-cn,🇬 谷歌服务
- RULE-SET,games-cn,🎮 游戏服务
- RULE-SET,ai,🤖 AI 平台
- RULE-SET,networktest,📈 网络测试
- - RULE-SET,proxy,🧱 代理域名
- - RULE-SET,cn,🛡️ 直连域名
+ - RULE-SET,proxy,🌎 国外域名
+ - RULE-SET,cn,🇨🇳 国内域名
- RULE-SET,privateip,🔒 私有网络,no-resolve
- - RULE-SET,cnip,🀄️ 直连 IP
+ - RULE-SET,cnip,🀄️ 国内 IP
- RULE-SET,telegramip,📲 电报消息,no-resolve
- - MATCH,🐟 漏网之鱼
\ No newline at end of file
+ - MATCH,🐟 漏网之鱼
diff --git a/rules/clash_providers/ShellCrash_Geo_Nano.yaml b/rules/clash_providers/ShellCrash_Geo_Nano.yaml
index ef33cc4e..d85795b6 100644
--- a/rules/clash_providers/ShellCrash_Geo_Nano.yaml
+++ b/rules/clash_providers/ShellCrash_Geo_Nano.yaml
@@ -1,7 +1,7 @@
#ShellCrash-geosite极简规则
proxy-groups:
- {name: 🚀 节点选择, type: select, proxies: [{providers_tags}], include-all: true}
- - {name: 🎯 全球直连, type: select, proxies: [DIRECT, 🚀 节点选择]}
+ - {name: 🎯 本地直连, type: select, proxies: [DIRECT, 🚀 节点选择]}
rules:
- - GEOIP,cn,🎯 全球直连
+ - GEOIP,cn,🎯 本地直连
- MATCH,🚀 节点选择
diff --git a/rules/clash_providers/ShellCrash_RS_Full_BanAds.yaml b/rules/clash_providers/ShellCrash_RS_Full_BanAds.yaml
index e959126c..281bc0b7 100644
--- a/rules/clash_providers/ShellCrash_RS_Full_BanAds.yaml
+++ b/rules/clash_providers/ShellCrash_RS_Full_BanAds.yaml
@@ -1,4 +1,4 @@
-#ShellCrash-ruleset 全分组规则+去广告 For mihomo By Maozai 260107
+#ShellCrash-ruleset 全分组规则+去广告 For mihomo By Maozai 260111
#此版本为Maozai根据ACL4SSR规则修改优化而来,尽量在保持原有的基础上进行优化。
#数据源采用了DustinWin/ruleset_geodata和MetaCubeX/meta-rules-dat两个开源项目的规则,感谢原作者的辛勤付出。
@@ -11,12 +11,12 @@ proxy-groups:
- {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|专线|专用|高级|直连|急速|高速|高倍率|游戏|铂金|钻石|企业|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}
- - {name: 🚑 故障转移, type: fallback, interval: 1800, include-all: true, hidden: true}
-
+ - {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|🇭🇰|港|🇲🇴|澳门|hk|hongkong|hong kong)", hidden: true}
+ - {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}]}
@@ -31,7 +31,6 @@ proxy-groups:
- {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}]}
@@ -45,10 +44,10 @@ proxy-groups:
- {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)"}
- - {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)(🇯🇵|日|东京|大阪|埼玉|九州|jp|japan)"}
- - {name: 🇪🇺 欧洲节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇪🇺|欧|德|英|法|荷|俄罗斯|西班牙|意大利|瑞士|瑞典|土耳其|挪威|芬兰|丹麦|比利时|爱尔兰|奥地利|波兰|葡萄牙|乌克兰|希腊|捷克|匈牙利|罗马尼亚|保加利亚|冰岛|克罗地亚)"}
+ - {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)"}
@@ -63,166 +62,152 @@ rule-providers:
interval: 86400
behavior: domain
proxy: DIRECT
- url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/ai.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/ai.mrs"
youtube:
type: http
format: mrs
interval: 86400
behavior: domain
proxy: DIRECT
- url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/youtube.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/youtube.mrs"
netflix:
type: http
format: mrs
interval: 86400
behavior: domain
proxy: DIRECT
- url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/netflix.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/netflix.mrs"
telegramip:
type: http
format: mrs
interval: 86400
behavior: ipcidr
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
- proxy: DIRECT
- url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/trackerslist.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/telegramip.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"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/applications.list"
private:
type: http
format: mrs
interval: 86400
behavior: domain
proxy: DIRECT
- url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/private.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/private.mrs"
privateip:
type: http
format: mrs
interval: 86400
behavior: ipcidr
proxy: DIRECT
- url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/privateip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/privateip.mrs"
networktest:
type: http
format: mrs
interval: 86400
behavior: domain
proxy: DIRECT
- url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/networktest.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/networktest.mrs"
apple-cn:
type: http
format: mrs
interval: 86400
behavior: domain
proxy: DIRECT
- url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/apple-cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/apple-cn.mrs"
google-cn:
type: http
format: mrs
interval: 86400
behavior: domain
proxy: DIRECT
- url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/google-cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/google-cn.mrs"
googlefcm:
type: http
format: mrs
interval: 86400
behavior: domain
proxy: DIRECT
- url: "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@refs/heads/meta/geo/geosite/googlefcm.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@meta/geo/geosite/googlefcm.mrs"
steamcn:
type: http
format: mrs
interval: 86400
behavior: domain
proxy: DIRECT
- url: "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@refs/heads/meta/geo/geosite/steam@cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@meta/geo/geosite/steam@cn.mrs"
microsoft-cn:
type: http
format: mrs
interval: 86400
behavior: domain
proxy: DIRECT
- url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/microsoft-cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/microsoft-cn.mrs"
games-cn:
type: http
format: mrs
interval: 86400
behavior: domain
proxy: DIRECT
- url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/games-cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/games-cn.mrs"
games:
type: http
format: mrs
interval: 86400
behavior: domain
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
- proxy: DIRECT
- url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/gamesip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/games.mrs"
mediaip:
type: http
format: mrs
interval: 86400
behavior: ipcidr
proxy: DIRECT
- url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/mediaip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/mediaip.mrs"
media:
type: http
format: mrs
interval: 86400
behavior: domain
proxy: DIRECT
- url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/media.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/media.mrs"
cnip:
type: http
format: mrs
interval: 86400
behavior: ipcidr
proxy: DIRECT
- url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cnip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/cnip.mrs"
proxy:
type: http
format: mrs
interval: 86400
behavior: domain
proxy: DIRECT
- url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/proxy.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/proxy.mrs"
cn:
type: http
format: mrs
interval: 86400
behavior: domain
proxy: DIRECT
- url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/cn.mrs"
ads:
type: http
format: mrs
interval: 86400
behavior: domain
proxy: DIRECT
- url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/ads.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/ads.mrs"
#规则顺序
rules:
- - DOMAIN-SUFFIX,captive.apple.com,DIRECT
- - DOMAIN-SUFFIX,kamo.teracloud.jp,DIRECT
+ - DOMAIN-SUFFIX,captive.apple.com,🍎 苹果服务
+ - DOMAIN-SUFFIX,kamo.teracloud.jp,🀄️ 国内流量
- RULE-SET,privateip,🔒 私有网络,no-resolve
- RULE-SET,private,🔒 私有网络
@@ -231,7 +216,6 @@ rules:
- RULE-SET,networktest,📈 网络测速
- RULE-SET,applications,↔️ 直连软件
- - RULE-SET,trackerslist,🧲 BT下载
- RULE-SET,apple-cn,🍎 苹果服务
- RULE-SET,microsoft-cn,🪟 微软服务
- RULE-SET,google-cn,🇬 谷歌服务
@@ -247,7 +231,6 @@ rules:
- RULE-SET,proxy,🌐 国际流量
- RULE-SET,cn,🀄️ 国内流量
- - RULE-SET,gamesip,🎮 外服游戏
- RULE-SET,mediaip,🌍 国际媒体
- RULE-SET,cnip,🀄️ 国内流量
diff --git a/rules/clash_providers/ShellCrash_RS_Nano.yaml b/rules/clash_providers/ShellCrash_RS_Nano.yaml
index 8630dee6..95137a98 100644
--- a/rules/clash_providers/ShellCrash_RS_Nano.yaml
+++ b/rules/clash_providers/ShellCrash_RS_Nano.yaml
@@ -1,31 +1,31 @@
#ShellCrash-ruleset极简规则
proxy-groups:
- {name: 🚀 节点选择, type: select, proxies: [{providers_tags}], include-all: true}
- - {name: 🎯 全球直连, type: select, proxies: [DIRECT, 🚀 节点选择]}
+ - {name: 🎯 本地直连, type: select, proxies: [DIRECT, 🚀 节点选择]}
rule-providers:
cn:
type: http
behavior: domain
format: mrs
path: ./ruleset/cn.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cn.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/cn.mrs"
interval: 86400
privateip:
type: http
behavior: ipcidr
format: mrs
path: ./ruleset/privateip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/privateip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/privateip.mrs"
interval: 86400
cnip:
type: http
behavior: ipcidr
format: mrs
path: ./ruleset/cnip.mrs
- url: "https://testingcf.jsdelivr.net/gh//DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cnip.mrs"
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@mihomo-ruleset/cnip.mrs"
interval: 86400
rules:
- - RULE-SET,privateip,🎯 全球直连,no-resolve
- - RULE-SET,cn,🎯 全球直连
- - RULE-SET,cnip,🎯 全球直连
+ - RULE-SET,privateip,🎯 本地直连,no-resolve
+ - RULE-SET,cn,🎯 本地直连
+ - RULE-SET,cnip,🎯 本地直连
- MATCH,🚀 节点选择
diff --git a/rules/singbox_providers/DustinWin_RS_Full.json b/rules/singbox_providers/DustinWin_RS_Full.json
index d2254cbd..2c17744a 100644
--- a/rules/singbox_providers/DustinWin_RS_Full.json
+++ b/rules/singbox_providers/DustinWin_RS_Full.json
@@ -3,17 +3,18 @@
"outbounds": [
{ "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": [ "🚀 节点选择", "👑 高级节点", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "📉 省流节点", {providers_tags} ] },
+ { "tag": "🤖 AI 平台", "type": "selector", "outbounds": [ "🚀 节点选择", "👑 高级节点", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "📉 省流节点", {providers_tags} ] },
{ "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": [ "🎯 本地直连", "🚀 节点选择" ] },
- { "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": [ "🚀 节点选择", "👑 高级节点", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "📉 省流节点", {providers_tags} ] },
+ { "tag": "🇨🇳 国内域名", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🀄️ 国内 IP", "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": [ "🔴 全球拦截", "🎯 本地直连" ] },
@@ -34,34 +35,27 @@
"rules": [
{ "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": [ "games" ], "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": [ "proxy" ], "outbound": "🌎 国外域名" },
+ { "rule_set": [ "cn" ], "outbound": "🇨🇳 国内域名" },
+ { "ip_is_private": true, "outbound": "🎯 本地直连" },
{ "rule_set": [ "telegramip" ], "outbound": "📲 电报消息" },
{ "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4", "match_only": true},
- { "rule_set": [ "cnip" ], "outbound": "🀄️ 直连 IP" },
- { "rule_set": [ "mediaip" ], "outbound": "🌍 国外媒体" },
- { "rule_set": [ "gamesip" ], "outbound": "🎮 游戏平台" }
+ { "rule_set": [ "cnip" ], "outbound": "🀄️ 国内 IP" },
+ { "rule_set": [ "netflixip" ], "outbound": "🎥 奈飞视频" },
+ { "rule_set": [ "mediaip" ], "outbound": "🌍 国外媒体" }
],
"rule_set": [
- {
- "tag": "private",
- "type": "remote",
- "format": "binary",
- "path": "./ruleset/private.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs",
- "download_detour": "DIRECT"
- },
{
"tag": "ads",
"type": "remote",
@@ -71,11 +65,11 @@
"download_detour": "DIRECT"
},
{
- "tag": "trackerslist",
+ "tag": "private",
"type": "remote",
"format": "binary",
- "path": "./ruleset/trackerslist.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/trackerslist.srs",
+ "path": "./ruleset/private.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs",
"download_detour": "DIRECT"
},
{
@@ -110,14 +104,6 @@
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games-cn.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",
- "download_detour": "DIRECT"
- },
{
"tag": "games",
"type": "remote",
@@ -126,6 +112,30 @@
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games.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",
+ "download_detour": "DIRECT"
+ },
{
"tag": "ai",
"type": "remote",
@@ -159,11 +169,11 @@
"download_detour": "DIRECT"
},
{
- "tag": "privateip",
+ "tag": "telegramip",
"type": "remote",
"format": "binary",
- "path": "./ruleset/privateip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs",
+ "path": "./ruleset/telegramip.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs",
"download_detour": "DIRECT"
},
{
@@ -174,6 +184,14 @@
"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",
@@ -181,22 +199,6 @@
"path": "./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",
- "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",
- "download_detour": "DIRECT"
}
],
"final": "🐟 漏网之鱼"
diff --git a/rules/singbox_providers/DustinWin_RS_Full_NoAds.json b/rules/singbox_providers/DustinWin_RS_Full_NoAds.json
index 4cae3ed6..488be16f 100644
--- a/rules/singbox_providers/DustinWin_RS_Full_NoAds.json
+++ b/rules/singbox_providers/DustinWin_RS_Full_NoAds.json
@@ -3,17 +3,18 @@
"outbounds": [
{ "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": [ "🚀 节点选择", "👑 高级节点", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "📉 省流节点", {providers_tags} ] },
+ { "tag": "🤖 AI 平台", "type": "selector", "outbounds": [ "🚀 节点选择", "👑 高级节点", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "📉 省流节点", {providers_tags} ] },
{ "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": [ "🎯 本地直连", "🚀 节点选择" ] },
- { "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": [ "🚀 节点选择", "👑 高级节点", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "📉 省流节点", {providers_tags} ] },
+ { "tag": "🇨🇳 国内域名", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🀄️ 国内 IP", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🌎 国外域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "📲 电报消息", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 本地直连" ] },
{ "tag": "🎯 本地直连", "type": "direct" },
@@ -31,24 +32,25 @@
"route": {
"rules": [
{ "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": [ "games" ], "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": [ "proxy" ], "outbound": "🌎 国外域名" },
+ { "rule_set": [ "cn" ], "outbound": "🇨🇳 国内域名" },
+ { "ip_is_private": true, "outbound": "🎯 本地直连" },
{ "rule_set": [ "telegramip" ], "outbound": "📲 电报消息" },
{ "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4", "match_only": true},
- { "rule_set": [ "cnip" ], "outbound": "🀄️ 直连 IP" },
- { "rule_set": [ "mediaip" ], "outbound": "🌍 国外媒体" },
- { "rule_set": [ "gamesip" ], "outbound": "🎮 游戏平台" }
+ { "rule_set": [ "cnip" ], "outbound": "🀄️ 国内 IP" },
+ { "rule_set": [ "netflixip" ], "outbound": "🎥 奈飞视频" },
+ { "rule_set": [ "mediaip" ], "outbound": "🌍 国外媒体" }
],
"rule_set": [
{
@@ -59,14 +61,6 @@
"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",
- "download_detour": "DIRECT"
- },
{
"tag": "microsoft-cn",
"type": "remote",
@@ -99,14 +93,6 @@
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games-cn.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",
- "download_detour": "DIRECT"
- },
{
"tag": "games",
"type": "remote",
@@ -115,6 +101,30 @@
"url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games.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",
+ "download_detour": "DIRECT"
+ },
{
"tag": "ai",
"type": "remote",
@@ -148,11 +158,11 @@
"download_detour": "DIRECT"
},
{
- "tag": "privateip",
+ "tag": "telegramip",
"type": "remote",
"format": "binary",
- "path": "./ruleset/privateip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs",
+ "path": "./ruleset/telegramip.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs",
"download_detour": "DIRECT"
},
{
@@ -163,6 +173,14 @@
"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",
@@ -170,22 +188,6 @@
"path": "./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",
- "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",
- "download_detour": "DIRECT"
}
],
"final": "🐟 漏网之鱼"
diff --git a/rules/singbox_providers/DustinWin_RS_Light.json b/rules/singbox_providers/DustinWin_RS_Light.json
index c94b6a50..95826472 100644
--- a/rules/singbox_providers/DustinWin_RS_Light.json
+++ b/rules/singbox_providers/DustinWin_RS_Light.json
@@ -2,7 +2,8 @@
{
"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": "direct" },
@@ -20,24 +21,15 @@
"route": {
"rules": [
{ "rule_set": [ "private" ], "outbound": "🎯 本地直连" },
- { "rule_set": [ "tld-proxy" ], "outbound": "🧱 代理域名" },
- { "rule_set": [ "proxy" ], "outbound": "🧱 代理域名" },
- { "rule_set": [ "cn" ], "outbound": "🎯 本地直连" },
- { "rule_set": [ "privateip" ], "outbound": "🎯 本地直连" },
+ { "rule_set": [ "tld-proxy" ], "outbound": "🌎 国外域名" },
+ { "rule_set": [ "proxy" ], "outbound": "🌎 国外域名" },
+ { "ip_is_private": true, "outbound": "🎯 本地直连" },
{ "rule_set": [ "telegramip" ], "outbound": "📲 电报消息" },
{ "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4", "match_only": true},
- { "rule_set": [ "cnip" ], "outbound": "🎯 本地直连" }
+ { "rule_set": [ "cnip" ], "outbound": "🀄️ 国内 IP" }
],
"rule_set": [
- {
- "tag": "cn",
- "type": "remote",
- "format": "binary",
- "path": "./ruleset/cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs",
- "download_detour": "DIRECT"
- },
{
"tag": "private",
"type": "remote",
@@ -63,11 +55,11 @@
"download_detour": "DIRECT"
},
{
- "tag": "privateip",
+ "tag": "telegramip",
"type": "remote",
"format": "binary",
- "path": "./ruleset/privateip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs",
+ "path": "./ruleset/telegramip.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs",
"download_detour": "DIRECT"
},
{
@@ -77,14 +69,6 @@
"path": "./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",
- "download_detour": "DIRECT"
}
],
"final": "🐟 漏网之鱼"
diff --git a/rules/singbox_providers/DustinWin_RS_Lite.json b/rules/singbox_providers/DustinWin_RS_Lite.json
index 44748625..5ee77e7f 100644
--- a/rules/singbox_providers/DustinWin_RS_Lite.json
+++ b/rules/singbox_providers/DustinWin_RS_Lite.json
@@ -3,15 +3,14 @@
"outbounds": [
{ "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 本地直连", {providers_tags} ] },
{ "tag": "📈 网络测试", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
- { "tag": "🤖 AI 平台", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点" ] },
- { "tag": "📋 Trackerslist", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🤖 AI 平台", "type": "selector", "outbounds": [ "🚀 节点选择", "👑 高级节点", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "📉 省流节点", {providers_tags} ] },
{ "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": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🀄️ 国内 IP", "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": [ "🔴 全球拦截", "🎯 本地直连" ] },
@@ -32,30 +31,21 @@
"rules": [
{ "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": [ "ai" ], "outbound": "🤖 AI 平台" },
{ "rule_set": [ "networktest" ], "outbound": "📈 网络测试" },
- { "rule_set": [ "proxy" ], "outbound": "🧱 代理域名" },
- { "rule_set": [ "cn" ], "outbound": "🛡️ 直连域名" },
- { "rule_set": [ "privateip" ], "outbound": "🎯 本地直连" },
+ { "rule_set": [ "proxy" ], "outbound": "🌎 国外域名" },
+ { "rule_set": [ "cn" ], "outbound": "🇨🇳 国内域名" },
+ { "ip_is_private": true, "outbound": "🎯 本地直连" },
{ "rule_set": [ "telegramip" ], "outbound": "📲 电报消息" },
{ "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4", "match_only": true},
- { "rule_set": [ "cnip" ], "outbound": "🀄️ 直连 IP" }
+ { "rule_set": [ "cnip" ], "outbound": "🀄️ 国内 IP" }
],
"rule_set": [
- {
- "tag": "private",
- "type": "remote",
- "format": "binary",
- "path": "./ruleset/private.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs",
- "download_detour": "DIRECT"
- },
{
"tag": "ads",
"type": "remote",
@@ -65,11 +55,11 @@
"download_detour": "DIRECT"
},
{
- "tag": "trackerslist",
+ "tag": "private",
"type": "remote",
"format": "binary",
- "path": "./ruleset/trackerslist.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/trackerslist.srs",
+ "path": "./ruleset/private.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs",
"download_detour": "DIRECT"
},
{
@@ -137,11 +127,11 @@
"download_detour": "DIRECT"
},
{
- "tag": "privateip",
+ "tag": "telegramip",
"type": "remote",
"format": "binary",
- "path": "./ruleset/privateip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs",
+ "path": "./ruleset/telegramip.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs",
"download_detour": "DIRECT"
},
{
@@ -151,14 +141,6 @@
"path": "./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",
- "download_detour": "DIRECT"
}
],
"final": "🐟 漏网之鱼"
diff --git a/rules/singbox_providers/DustinWin_RS_Lite_NoAds.json b/rules/singbox_providers/DustinWin_RS_Lite_NoAds.json
index a5eba229..76df0ae4 100644
--- a/rules/singbox_providers/DustinWin_RS_Lite_NoAds.json
+++ b/rules/singbox_providers/DustinWin_RS_Lite_NoAds.json
@@ -3,15 +3,14 @@
"outbounds": [
{ "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 本地直连", {providers_tags} ] },
{ "tag": "📈 网络测试", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
- { "tag": "🤖 AI 平台", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点" ] },
- { "tag": "📋 Trackerslist", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🤖 AI 平台", "type": "selector", "outbounds": [ "🚀 节点选择", "👑 高级节点", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "📉 省流节点", {providers_tags} ] },
{ "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": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🀄️ 国内 IP", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🌎 国外域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "📲 电报消息", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 本地直连" ] },
{ "tag": "🎯 本地直连", "type": "direct" },
@@ -29,20 +28,19 @@
"route": {
"rules": [
{ "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": [ "ai" ], "outbound": "🤖 AI 平台" },
{ "rule_set": [ "networktest" ], "outbound": "📈 网络测试" },
- { "rule_set": [ "proxy" ], "outbound": "🧱 代理域名" },
- { "rule_set": [ "cn" ], "outbound": "🛡️ 直连域名" },
- { "rule_set": [ "privateip" ], "outbound": "🎯 本地直连" },
+ { "rule_set": [ "proxy" ], "outbound": "🌎 国外域名" },
+ { "rule_set": [ "cn" ], "outbound": "🇨🇳 国内域名" },
+ { "ip_is_private": true, "outbound": "🎯 本地直连" },
{ "rule_set": [ "telegramip" ], "outbound": "📲 电报消息" },
{ "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4", "match_only": true},
- { "rule_set": [ "cnip" ], "outbound": "🀄️ 直连 IP" }
+ { "rule_set": [ "cnip" ], "outbound": "🀄️ 国内 IP" }
],
"rule_set": [
@@ -54,14 +52,6 @@
"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",
- "download_detour": "DIRECT"
- },
{
"tag": "microsoft-cn",
"type": "remote",
@@ -127,11 +117,11 @@
"download_detour": "DIRECT"
},
{
- "tag": "privateip",
+ "tag": "telegramip",
"type": "remote",
"format": "binary",
- "path": "./ruleset/privateip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs",
+ "path": "./ruleset/telegramip.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs",
"download_detour": "DIRECT"
},
{
@@ -141,14 +131,6 @@
"path": "./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",
- "download_detour": "DIRECT"
}
],
"final": "🐟 漏网之鱼"
diff --git a/rules/singbox_providers/ShellCrash_RS_Full_BanAds.json b/rules/singbox_providers/ShellCrash_RS_Full_BanAds.json
index d771d946..262e73aa 100644
--- a/rules/singbox_providers/ShellCrash_RS_Full_BanAds.json
+++ b/rules/singbox_providers/ShellCrash_RS_Full_BanAds.json
@@ -1,4 +1,4 @@
-//ShellCrash-ruleset 全分组规则+去广告 For Sing-box By Maozai 260107
+//ShellCrash-ruleset 全分组规则+去广告 For Sing-box By Maozai 260111
{
"outbounds": [
{ "tag": "🚀 节点选择", "type": "selector", "outbounds": ["♻️ 自动选择", "✨ 自动选择(去高倍率)", "🛠️ 手动切换", "🎯 本地直连", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
@@ -11,7 +11,7 @@
{ "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}] },
@@ -22,25 +22,23 @@
{ "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": "selector", "outbounds": ["⛔ 禁止连接", "🔀 规则放行", "🎯 本地直连"] },
{ "tag": "⛔ 禁止连接", "type": "block" },
{ "tag": "🔀 规则放行", "type": "pass" },
{ "tag": "🎯 本地直连", "type": "direct" },
- { "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
+ { "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)" },
- { "tag": "🇺🇸 美国节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(🇺🇸|美|洛杉矶|圣何塞|西雅图|纽约|波特兰|旧金山|us|unitedstates|united states)" },
- { "tag": "🇯🇵 日本节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(🇯🇵|日|东京|大阪|埼玉|九州|jp|japan)" },
- { "tag": "🇪🇺 欧洲节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(🇪🇺|欧|德|英|法|荷|俄罗斯|西班牙|意大利|瑞士|瑞典|土耳其|挪威|芬兰|丹麦|比利时|爱尔兰|奥地利|波兰|葡萄牙|乌克兰|希腊|捷克|匈牙利|罗马尼亚|保加利亚|冰岛|克罗地亚)" },
+ { "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)" },
@@ -49,15 +47,14 @@
],
"route": {
"rules": [
- { "domain_suffix": ["captive.apple.com"], "outbound": "DIRECT" },
- { "domain_suffix": ["kamo.teracloud.jp"], "outbound": "DIRECT" },
-
+ { "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": "🇬 谷歌服务" },
@@ -78,7 +75,6 @@
{ "rule_set": ["telegramip"], "outbound": "📲 电报消息" },
{ "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4" },
- { "rule_set": ["gamesip"], "outbound": "🎮 外服游戏" },
{ "rule_set": ["mediaip"], "outbound": "🌍 国际媒体" },
{ "rule_set": ["cnip"], "outbound": "🀄️ 国内流量" }
],
@@ -88,7 +84,7 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/private.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/private.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs",
"download_detour": "DIRECT"
},
{
@@ -96,7 +92,7 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/ads.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/ads.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ads.srs",
"download_detour": "DIRECT"
},
{
@@ -104,7 +100,7 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/networktest.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/networktest.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/networktest.srs",
"download_detour": "DIRECT"
},
{
@@ -112,15 +108,7 @@
"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",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/applications.srs",
"download_detour": "DIRECT"
},
{
@@ -128,7 +116,7 @@
"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",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/apple-cn.srs",
"download_detour": "DIRECT"
},
{
@@ -136,7 +124,7 @@
"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",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/microsoft-cn.srs",
"download_detour": "DIRECT"
},
{
@@ -144,7 +132,7 @@
"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",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/google-cn.srs",
"download_detour": "DIRECT"
},
{
@@ -152,7 +140,7 @@
"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",
+ "url": "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@sing/geo/geosite/steam%40cn.srs",
"download_detour": "DIRECT"
},
{
@@ -160,7 +148,7 @@
"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",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games-cn.srs",
"download_detour": "DIRECT"
},
{
@@ -168,7 +156,7 @@
"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",
+ "url": "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@sing/geo/geosite/googlefcm.srs",
"download_detour": "DIRECT"
},
{
@@ -176,7 +164,7 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/netflix.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/netflix.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/netflix.srs",
"download_detour": "DIRECT"
},
{
@@ -184,7 +172,7 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/youtube.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/youtube.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/youtube.srs",
"download_detour": "DIRECT"
},
{
@@ -192,7 +180,7 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/ai.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/ai.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ai.srs",
"download_detour": "DIRECT"
},
{
@@ -200,7 +188,7 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/media.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/media.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/media.srs",
"download_detour": "DIRECT"
},
{
@@ -208,7 +196,7 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/games.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/games.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games.srs",
"download_detour": "DIRECT"
},
{
@@ -216,7 +204,7 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/proxy.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/proxy.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs",
"download_detour": "DIRECT"
},
{
@@ -224,7 +212,7 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/cn.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs",
"download_detour": "DIRECT"
},
{
@@ -232,7 +220,7 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/privateip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/privateip.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs",
"download_detour": "DIRECT"
},
{
@@ -240,15 +228,7 @@
"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",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs",
"download_detour": "DIRECT"
},
{
@@ -256,7 +236,7 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/mediaip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/mediaip.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/mediaip.srs",
"download_detour": "DIRECT"
},
{
@@ -264,7 +244,7 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/cnip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/cnip.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs",
"download_detour": "DIRECT"
}
],
diff --git a/rules/singbox_providers/ShellCrash_RS_Nano.json b/rules/singbox_providers/ShellCrash_RS_Nano.json
index 1a08c9b9..9353091a 100644
--- a/rules/singbox_providers/ShellCrash_RS_Nano.json
+++ b/rules/singbox_providers/ShellCrash_RS_Nano.json
@@ -6,7 +6,7 @@
],
"route": {
"rules": [
- { "rule_set": [ "privateip" ], "outbound": "🎯 本地直连" },
+ { "ip_is_private": true, "outbound": "🎯 本地直连" },
{ "rule_set": [ "cn" ], "outbound": "🎯 本地直连" },
{ "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4", "match_only": true},
@@ -21,14 +21,6 @@
"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",
- "download_detour": "DIRECT"
- },
{
"tag": "cnip",
"type": "remote",
diff --git a/scripts/init.sh b/scripts/init.sh
index 800c4fcf..00d7a4b8 100644
--- a/scripts/init.sh
+++ b/scripts/init.sh
@@ -17,13 +17,16 @@
[ -f "/data/etc/crontabs/root" ] && systype=mi_snapshot #小米设备
[ -w "/var/mnt/cfg/firewall" ] && systype=ng_snapshot #NETGEAR设备
#容器内环境
-grep -qE '/(docker|lxc|kubepods|crio|containerd)/' /proc/1/cgroup || [ -f /run/.containerenv ] || [ -f /.dockerenv ] && systype='container'
+grep -qE '/(docker|lxc|kubepods|crio|containerd)/' /proc/1/cgroup 2>/dev/null || [ -f /run/.containerenv ] || [ -f /.dockerenv ] && systype='container'
#检查环境变量
[ "$systype" = 'container' ] && CRASHDIR='/etc/ShellCrash'
[ -z "$CRASHDIR" ] && [ -n "$clashdir" ] && CRASHDIR="$clashdir"
[ -z "$CRASHDIR" ] && [ -d /tmp/SC_tmp ] && . /tmp/SC_tmp/menus/set_crashdir.sh && set_crashdir
+CRASHDIR=$(echo "$CRASHDIR" | sed 's#/*$##') #删除末尾的/
+TASKCFGDIR="$CRASHDIR"/configs/task
#移动文件
mkdir -p "$CRASHDIR"
+mkdir -p "$TASKCFGDIR"
rm -rf /tmp/SC_tmp/menus/set_crashdir.sh
mv -f /tmp/SC_tmp/* "$CRASHDIR" 2>/dev/null
##############################
@@ -37,11 +40,11 @@ mkdir -p "$CRASHDIR"/configs
#判断系统类型写入不同的启动文件
[ -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
+if [ -f /etc/rc.common -a "$(cat /proc/1/comm 2>/dev/null)" = "procd" ]; then
#设为init.d方式启动
cp -f "$CRASHDIR"/starts/shellcrash.procd /etc/init.d/shellcrash
chmod 755 /etc/init.d/shellcrash
-elif [ -n "$sysdir" -a "$USER" = "root" -a "$(cat /proc/1/comm)" = "systemd" ]; then
+elif [ -n "$sysdir" -a "$USER" = "root" -a "$(cat /proc/1/comm 2>/dev/null)" = "systemd" ]; then
#创建shellcrash用户
userdel shellcrash 2>/dev/null
sed -i '/0:7890/d' /etc/passwd
@@ -56,7 +59,7 @@ elif [ -n "$sysdir" -a "$USER" = "root" -a "$(cat /proc/1/comm)" = "systemd" ];
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
+ rm -rf "$CRASHDIR"/starts/shellcrash.procd
elif rc-status -r >/dev/null 2>&1; then
#设为openrc方式启动
mv -f "$CRASHDIR"/starts/shellcrash.openrc /etc/init.d/shellcrash
@@ -65,7 +68,7 @@ elif rc-status -r >/dev/null 2>&1; then
else
#设为保守模式启动
setconfig start_old 已开启
- rm -rf "$CRASHDIR"/starts/shellcrash.procd
+ rm -rf "$CRASHDIR"/starts/shellcrash.procd
fi
rm -rf "$CRASHDIR"/starts/shellcrash.service
rm -rf "$CRASHDIR"/starts/shellcrash.openrc
@@ -81,11 +84,8 @@ done
setconfig versionsh_l $version
#生成用于执行启动服务的变量文件
[ ! -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
+ echo 'TMPDIR=/tmp/ShellCrash' > "$CRASHDIR"/configs/command.env
+ echo "BINDIR=$CRASHDIR" >> "$CRASHDIR"/configs/command.env
}
if [ -n "$(grep 'crashcore=singbox' "$CFG_PATH")" ]; then
COMMAND='"$TMPDIR/CrashCore run -D $BINDIR -C $TMPDIR/jsons"'
@@ -100,7 +100,10 @@ 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 ] && [ "$systype" = "Padavan" ] && profile=/opt/etc/profile
[ -w /jffs/configs/profile.add ] && profile=/jffs/configs/profile.add
@@ -116,10 +119,10 @@ else
fi
#梅林/Padavan额外设置
[ -n "$initdir" ] && {
- touch "$initdir"
+ touch "$initdir"
sed -i '/ShellCrash初始化/'d "$initdir"
echo "$CRASHDIR/starts/general_init.sh & #ShellCrash初始化脚本" >>"$initdir"
- chmod 755 "$CRASHDIR"/starts/general_init.sh
+ chmod 755 "$CRASHDIR"/starts/general_init.sh
chmod a+rx "$initdir" 2>/dev/null
setconfig initdir "$initdir"
}
@@ -128,14 +131,14 @@ fi
#镜像化OpenWrt(snapshot)额外设置
if [ "$systype" = "mi_snapshot" -o "$systype" = "ng_snapshot" ]; then
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
+ 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
@@ -157,15 +160,15 @@ fi
sed -i "/^PATH=/a\\$CRASHDIR/start.sh init & #ShellCrash初始化脚本" "$dir/asusware.arm/etc/init.d/S50downloadmaster"
#容器环境额外设置
[ "$systype" = 'container' ] && {
- setconfig userguide '1'
- setconfig crashcore 'meta'
- setconfig dns_mod 'mix'
- setconfig firewall_area '1'
- setconfig firewall_mod 'nftables'
- setconfig release_type 'master'
- setconfig start_old 'OFF'
- echo "$CRASHDIR/menu.sh" >> /etc/profile
- cat > /usr/bin/crash <<'EOF'
+ setconfig userguide '1'
+ setconfig crashcore 'meta'
+ setconfig dns_mod 'mix'
+ setconfig firewall_area '1'
+ setconfig firewall_mod 'nftables'
+ setconfig release_type 'master'
+ setconfig start_old 'OFF'
+ echo "$CRASHDIR/menu.sh" >> /etc/profile
+ cat > /usr/bin/crash <<'EOF'
#!/bin/sh
CRASHDIR=${CRASHDIR:-/etc/ShellCrash}
export CRASHDIR
@@ -187,9 +190,18 @@ for file in config.yaml.bak user.yaml proxies.yaml proxy-groups.yaml rules.yaml
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
-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
+for file in fake_ip_filter mac web_save servers_chs.list servers_en.list fake_ip_filter.list singbox_providers.list clash_providers.list; do
mv -f "$CRASHDIR"/"$file" "$CRASHDIR"/configs/"$file" 2>/dev/null
done
+#迁移任务状态文件到新目录
+for file in cron bfstart afstart running affirewall task.user; do
+ mv -f "$CRASHDIR"/"$file" "$TASKCFGDIR"/"$file" 2>/dev/null
+ mv -f "$CRASHDIR"/task/"$file" "$TASKCFGDIR"/"$file" 2>/dev/null
+done
+#修正旧版防火墙注入路径
+for file in /etc/init.d/firewall /etc/init.d/firewall.bak; do
+ [ -f "$file" ] && sed -i "s#$CRASHDIR/task/affirewall#$TASKCFGDIR/affirewall#g" "$file" 2>/dev/null
+done
#配置文件改名
mv -f "$CRASHDIR"/configs/ShellClash.cfg "$CFG_PATH" 2>/dev/null
#数据库改名
@@ -202,7 +214,7 @@ 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
done
-for file in cron task.list; do
+for file in cron task_chs.list task_en.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
@@ -213,7 +225,7 @@ sed -i '/shellclash/d' /etc/group
rm -rf /etc/init.d/clash
rm -rf "$CRASHDIR"/rules
[ "$systype" = "mi_snapshot" -a "$CRASHDIR" != '/data/clash' ] && rm -rf /data/clash
-for file in webget.sh misnap_init.sh core.new; do
+for file in webget.sh misnap_init.sh core.new configs/ShellCrash.cfg.bak; do
rm -f "$CRASHDIR/$file"
done
#旧版变量改名
@@ -222,12 +234,13 @@ 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=Nft基础/redir_mod=Redir模式/g" "$CFG_PATH"
-sed -i "s/redir_mod=Nft混合/redir_mod=Tproxy模式/g" "$CFG_PATH"
-sed -i "s/redir_mod=Tproxy混合/redir_mod=Tproxy模式/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"
diff --git a/scripts/lang/chs/1_start.lang b/scripts/lang/chs/1_start.lang
new file mode 100644
index 00000000..a21e148a
--- /dev/null
+++ b/scripts/lang/chs/1_start.lang
@@ -0,0 +1,10 @@
+# ===== 启动完成 =====
+START_SERVICE_OK="服务已启动!"
+START_WEB_HINT="管理面板:"
+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="已完成防火墙设置!"
diff --git a/scripts/lang/chs/2_settings.lang b/scripts/lang/chs/2_settings.lang
new file mode 100644
index 00000000..802b4c4e
--- /dev/null
+++ b/scripts/lang/chs/2_settings.lang
@@ -0,0 +1,164 @@
+# =================================================
+# Settings main menu
+# =================================================
+SET_MENU_TITLE="功能设置菜单"
+SET_MENU_REDIR="路由模式设置:"
+SET_MENU_DNS="DNS设置: "
+SET_MENU_FW_FILTER="透明路由流量过滤:"
+SET_MENU_FW_FILTER_DESC="端口、设备、协议或列表"
+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转发TCP,Tun转发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地址)"
+SET_YES="是"
+SET_NO_BACK="否,返回上级菜单"
+SET_SKIP_CERT_NOW="当前"
+SET_ENABLED="已启用"
+SET_DISABLED="已禁用"
+SET_SKIP_CERT_ENABLE_Q="跳过本地证书验证,是否确认启用?"
+SET_SKIP_CERT_DISABLE_Q="跳过本地证书验证,是否确认禁用?"
+SET_SNIFFER_NOW="当前"
+SET_SNIFFER_ENABLE_Q="域名嗅探,是否确认启用?"
+SET_SNIFFER_DISABLE_Q="域名嗅探,是否确认禁用?"
+SET_LANG_ZH="简体中文"
+SET_LANG_EN="English"
+SET_SWITCH_RERUN="切换成功!请重新运行脚本!"
+SET_SWITCH_OK="切换成功!"
+SET_MODE_SUFFIX="模式"
+SET_SET_TO="设为"
+SET_BYPASS_TCP="TCP旁路转发"
+SET_BYPASS_TU="T&U旁路转发"
+SET_BYPASS_TCP_DESC="仅转发TCP流量至旁路由"
+SET_BYPASS_TU_DESC="转发TCP&UDP流量至旁路由"
+SET_FW_AREA_CURRENT="当前路由劫持范围:"
+SET_WARN="注意:"
+SET_DESC="说明:"
+SET_BYPASS_WARN_1="此功能存在多种风险如无网络基础请勿尝试!"
+SET_BYPASS_WARN_2="如需代理UDP,请确保旁路由运行了支持UDP代理的模式!"
+SET_BYPASS_WARN_3="如使用systemd方式启动,内核依然会空载运行,建议使用保守模式!"
+SET_BYPASS_DESC_1="此功能不启动内核仅配置防火墙转发,且子设备无需额外设置网关DNS"
+SET_BYPASS_DESC_2="支持防火墙分流及设备过滤,支持部分定时任务,但不支持ipv6"
+SET_INPUT_BYPASS_IPV4="请直接输入旁路由IPV4地址"
+SET_TIPS_ENTER_BACK="Tips:直接回车确认可返回上级菜单"
diff --git a/scripts/lang/chs/5_task.lang b/scripts/lang/chs/5_task.lang
new file mode 100644
index 00000000..4bc90172
--- /dev/null
+++ b/scripts/lang/chs/5_task.lang
@@ -0,0 +1,100 @@
+# 推荐任务配置
+TASK_RECOM_TITLE="是否启用以下推荐的自动任务配置:"
+
+TASK_RECOM_ITEM_1="运行时每10分钟自动保存面板配置"
+TASK_RECOM_ITEM_2="服务启动后自动同步 NTP 时间"
+TASK_RECOM_ITEM_3="在每日的3点0分重启服务"
+TASK5_RUN_TASK="执行任务:"
+TASK5_CONFIRM_ADD_CRON="是否确认添加定时任务?"
+TASK5_YES="是"
+TASK5_NO="否"
+TASK5_TASK_PREFIX="任务【"
+TASK5_TASK_ADDED="】\033[32m已添加!\033[0m"
+TASK5_USER_ADD_HINT1="命令可包含空格,请确保命令可执行!"
+TASK5_USER_ADD_HINT2="请勿附带执行条件,执行条件请在命令添加完成后再返回设置!"
+TASK5_USER_ADD_HINT3="亦可手动编辑"
+TASK5_USER_ADD_HINT4="以添加命令"
+TASK5_INPUT_CMD="请直接输入命令语句"
+TASK5_OR_BACK="或输入 0 返回上级菜单"
+TASK5_INPUT="请输入"
+TASK5_CHECK_INPUT="请检查输入:"
+TASK5_INPUT_REMARK="请输入任务备注"
+TASK5_CUSTOM_TASK="自定义任务"
+TASK5_CUSTOM_ADDED="自定义任务已添加!"
+TASK5_INPUT_ERROR="输入错误,请重新输入!"
+TASK5_USER_DEL_HINT1="请输入对应ID移除对应自定义任务(不会影响内置任务)"
+TASK5_USER_DEL_HINT2="也可以手动编辑"
+TASK5_NO_CUSTOM_TASK="你暂未添加任何自定义任务"
+TASK5_SELECT_ADD="请选择需要添加的任务:"
+TASK5_SELECT_COND="请选择任务"
+TASK5_SELECT_COND2="执行条件:"
+TASK5_COND_1="定时任务\033[32m每周执行\033[0m"
+TASK5_COND_2="定时任务\033[32m每日执行\033[0m"
+TASK5_COND_3="定时任务\033[32m每小时执行\033[0m"
+TASK5_COND_4="定时任务\033[32m每分钟执行\033[0m"
+TASK5_WARN_LINE1=" - - - - - - - - -\033[31m注意\033[0m- - - - - - - - -"
+TASK5_WARN_LINE2=" 逻辑水平不及格的请勿使用下方触发条件!"
+TASK5_WARN_LINE3=" - - - - - - - - - - - - - - - - - - - -"
+TASK5_COND_5="服务\033[33m启动前执行\033[0m"
+TASK5_COND_6="服务\033[33m启动后执行\033[0m"
+TASK5_COND_7="服务\033[33m运行时每分钟执行\033[0m"
+TASK5_COND_8="防火墙服务\033[33m重启后执行\033[0m"
+TASK5_WEEK_HINT1="输入 1~7 对应\033[33m每周的指定某天\033[0m运行(7=周日)"
+TASK5_WEEK_HINT2="输入 1,4,0 代表\033[36m每周一、周四、周日\033[0m运行"
+TASK5_WEEK_HINT3="输入 1~5 代表\033[36m周一至周五\033[0m运行"
+TASK5_WEEK_INPUT="在每周哪天执行?"
+TASK5_HOUR_INPUT1="想在该日的具体哪个小时执行?(0~23)"
+TASK5_CRON_WEEK="在每周"
+TASK5_CRON_WEEK2="的"
+TASK5_OCLOCK="点整"
+TASK5_DAY_HINT1="输入 1,7,15 代表\033[36m每到1,7,15点\033[0m运行"
+TASK5_DAY_HINT2="输入 6~18 代表\033[36m早6点至晚18点间每小时\033[0m运行"
+TASK5_HOUR_INPUT2="想在每日的具体哪个小时执行?(0~23)"
+TASK5_MIN_INPUT="想在具体哪分钟执行?(0~59的整数)"
+TASK5_CRON_DAY="在每日的"
+TASK5_POINT="点"
+TASK5_MINUTE="分"
+TASK5_EVERY_HOUR_INPUT="想每隔多少小时执行一次?(1~23的整数)"
+TASK5_EVERY="每隔"
+TASK5_HOUR="小时"
+TASK5_EVERY_MIN_INPUT="想每隔多少分钟执行一次?(1~59的整数)"
+TASK5_MIN="分钟"
+TASK5_BFSTART="服务启动前"
+TASK5_AFSTART="服务启动后"
+TASK5_RUNNING_HINT1="输入10即每隔10分钟运行一次,1440即每隔24小时运行一次"
+TASK5_RUNNING_HINT2="大于60分钟的数值将按小时取整,且按当前时区记时"
+TASK5_RUNNING_INPUT="想每隔多少分钟执行一次?(1~1440的整数)"
+TASK5_RUNNING_PREFIX="运行时每"
+TASK5_AFFW_HINT="该功能会将相关启动代码注入到/etc/init.d/firewall中"
+TASK5_CONFIRM_CONTINUE="是否确认继续?"
+TASK5_AFFW_PREFIX="防火墙重启后"
+TASK5_GUARD_WORD="守护"
+TASK5_OLD_PREFIX="旧版任务-"
+TASK5_NONE_TO_MANAGE="当前没有可供管理的任务!"
+TASK5_ADDED_TASKS="已添加的任务:"
+TASK5_CLEAR_OLD="清空旧版任务"
+TASK5_CLEAR_ALL="清空任务列表"
+TASK5_OLD_CLEARED="旧版任务已清空!"
+TASK5_ALL_CLEARED="全部任务已清空!"
+TASK5_OLD_NOT_SUPPORT="旧版任务不支持管理,是否移除?"
+TASK5_NO_BACK="否,返回上级菜单"
+TASK5_CURRENT_TASK="当前任务为:"
+TASK5_EDIT_TASK="\033[33m修改\033[0m当前任务"
+TASK5_DEL_TASK="\033[31m删除\033[0m当前任务"
+TASK5_RUN_ONCE="\033[32m立即执行\033[0m一次"
+TASK5_VIEW_RECORD="查看\033[33m执行记录\033[0m"
+TASK5_RUN_OK="执行成功!"
+TASK5_RUN_FAIL="执行失败!"
+TASK5_RECORD_NOT_FOUND="未找到相关执行记录!"
+TASK5_USER_FILE_HEADER="#任务ID(必须>200并顺序排列)#任务命令#任务说明(#号隔开,任务命令和说明中都不允许包含#号)"
+TASK5_MENU_TITLE="自动任务菜单"
+TASK5_MENU_1="添加\033[32m自动任务\033[0m"
+TASK5_MENU_2="管理\033[33m任务列表\033[0m"
+TASK5_MENU_3="查看\033[36m任务日志\033[0m"
+TASK5_MENU_4="配置\033[36m日志推送\033[0m"
+TASK5_MENU_5="添加\033[33m自定义任务\033[0m"
+TASK5_MENU_6="删除\033[33m自定义任务\033[0m"
+TASK5_MENU_7="使用\033[32m推荐设置\033[0m"
+TASK5_TASK_GREP="任务【"
+TASK5_LOG_NOT_FOUND="未找到任务相关执行日志!"
+TASK5_PUSH_HINT="请在日志工具中配置相关推送通道及推送开关"
diff --git a/scripts/lang/chs/6_core_config.lang b/scripts/lang/chs/6_core_config.lang
new file mode 100644
index 00000000..119c5154
--- /dev/null
+++ b/scripts/lang/chs/6_core_config.lang
@@ -0,0 +1,67 @@
+CORECFG_TITLE="配置文件管理"
+CORECFG_HINT_SELECT_PROVIDER="输入数字可管理对应提供者"
+CORECFG_MENU_A="\033[32m添加提供者\033[0m(支持订阅/分享链接及本地文件)"
+CORECFG_MENU_B="\033[36m本地生成配置文件\033[0m"
+CORECFG_MENU_C="\033[33m在线生成配置文件\033[0m"
+CORECFG_MENU_D="\033[31m清空提供者列表\033[0m"
+CORECFG_MENU_E="\033[36m自定义配置文件\033[0m"
+CORECFG_CORE_ONLY="仅限Mihomo/singboxr内核使用,请更换内核!"
+CORECFG_ADD_PROVIDER_FIRST="请先添加提供者!"
+CORECFG_CLEAR_WARN="警告:这将删除所有提供者且无法还原!"
+CORECFG_CLEAR_CONFIRM="是否确认清空提供者列表:"
+CORECFG_YES="是"
+CORECFG_NO="否"
+CORECFG_NO_BACK="否,返回上级菜单"
+CORECFG_INPUT_ALNUM="请输入对应字母或数字"
+CORECFG_INPUT="请输入"
+CORECFG_FILL_REQUIRED="请先完成必填选项!"
+CORECFG_START_APPLY="是否启动服务以使配置文件生效:"
+CORECFG_PROVIDER_SUPPORT="支持添加订阅链接/分享链接/本地文件作为提供者"
+CORECFG_SET_NAME="设置\033[36m名称或代号\033[0m\t"
+CORECFG_SET_LINK="设置\033[32m链接或路径\033[0m:\t"
+CORECFG_SET_OVERRIDE="设置\033[33m本地生成覆写\033[0m"
+CORECFG_SAVE_PROVIDER="\033[36m保存此提供者\033[0m"
+CORECFG_DEL_PROVIDER="\033[31m删除此提供者\033[0m"
+CORECFG_MORE_CONFIG_HINT="以下方式的详细配置请前往对应功能页面进行设置!"
+CORECFG_GEN_LOCAL_ONE="\033[32m本地生成\033[0m仅包含此提供者的配置文件"
+CORECFG_GEN_ONLINE_ONE="\033[33m在线生成\033[0m仅包含此提供者的配置文件"
+CORECFG_GET_ONLINE_DIRECT="在线获取此配置文件(不使用订阅转换)"
+CORECFG_USE_DIRECT="直接使用此文件作为配置文件(不使用本地生成)"
+CORECFG_NAME_HINT="注意:\n名称或代号不可重复,不支持纯数字,且不要超过4个汉字!"
+CORECFG_INPUT_NAME="请直接输入具体名称或代号"
+CORECFG_OR_BACK="或输入 0 返回上级菜单"
+CORECFG_LINK_HINT1="\033[33m订阅链接\033[0m:\nhttps/http开头的clash配置文件订阅链接"
+CORECFG_LINK_HINT2="\033[36m分享链接\033[0m:"
+CORECFG_LINK_HINT3="\033[33m本地文件\033[0m:\n必须放在"
+CORECFG_LINK_HINT4="目录下"
+CORECFG_LINK_HINT5="\033[36mBase64 \033[0m:\n请直接写入本地文件"
+CORECFG_INPUT0_BACK="输入 0 返回上级菜单"
+CORECFG_SELECT_FILE_OR_LINK="请选择对应文件或输入具体链接"
+CORECFG_INPUT_LINK="请直接输入具体链接"
+CORECFG_DANGER1="注意:\n此功能不兼容“跳过证书验证”功能"
+CORECFG_DANGER2="请确认你完全理解自己在做什么"
+CORECFG_DANGER_CONFIRM="我确认遇到问题可以自行解决"
+CORECFG_INTERVAL1="设置\033[33m健康检查间隔\033[0m:\t"
+CORECFG_INTERVAL2="设置\033[36m自动更新间隔\033[0m:\t"
+CORECFG_MIN="分钟"
+CORECFG_HOUR="小时"
+CORECFG_SET_UA="设置\033[33m虚拟浏览器UA\033[0m:\t"
+CORECFG_SET_EXCLUDE="设置\033[31m排除节点正则\033[0m:\t"
+CORECFG_SET_INCLUDE="设置\033[32m包含节点正则\033[0m:\t"
+CORECFG_CUR_INTERVAL="当前健康检查间隔:"
+CORECFG_INPUT_INTERVAL1="请直接健康检查间隔(单位:分钟)"
+CORECFG_RESET_INTERVAL1="或输入 r 重置健康检查间隔为默认值(3 分钟)"
+CORECFG_INPUT_INTERVAL2="请直接输入自动更新间隔(单位:小时)"
+CORECFG_RESET_INTERVAL2="或输入 r 重置自动更新间隔为默认值(12 小时)"
+CORECFG_CUR_UA_NONE="当前浏览器UA:无"
+CORECFG_CUR_UA="当前浏览器UA:"
+CORECFG_INPUT_UA="请直接输入浏览器UA"
+CORECFG_RESET_UA="或输入 r 重置浏览器UA为默认值(clash.meta)"
+CORECFG_CUR_EXCLUDE_NONE="当前排除规则:无"
+CORECFG_CUR_EXCLUDE="当前排除规则:"
+CORECFG_INPUT_EXCLUDE="请直接输入需要排除的节点关键字(支持正则,不支持空格)"
+CORECFG_CLEAR_EXCLUDE="或输入 c 清空排除规则"
+CORECFG_CUR_INCLUDE_NONE="当前包含规则:无"
+CORECFG_CUR_INCLUDE="当前包含规则:"
+CORECFG_INPUT_INCLUDE="请直接输入需要包含的节点关键字(支持正则,不支持空格)"
+CORECFG_CLEAR_INCLUDE="或输入 c 清空包含规则"
diff --git a/scripts/lang/chs/7_gateway.lang b/scripts/lang/chs/7_gateway.lang
new file mode 100644
index 00000000..128508c6
--- /dev/null
+++ b/scripts/lang/chs/7_gateway.lang
@@ -0,0 +1,97 @@
+GW_TITLE="访问与控制菜单"
+GW_WARN="注意:"
+GW_FW_VPS_HINT="如在vps运行,还需在vps安全策略对相关端口同时放行"
+GW_FW_PORT_LIMIT="最多支持设置放行10个端口,请先减少一些!"
+GW_INPUT_ALLOW_PORT="请输入要放行的端口号"
+GW_OK="操作成功"
+GW_CORE_UNSUPPORTED="内核暂不支持此功能,请先更换内核!"
+GW_TG_DONE_PREFIX="已完成Telegram机器人设置!请使用"
+GW_TG_DONE_SUFFIX="呼出功能菜单!"
+GW_SET="已设置"
+GW_BOUND="已绑定"
+GW_INPUT_PORT_DEL0="请输入端口号(输入0删除)"
+GW_INPUT_WSPATH="请输入ws-path路径(输入0删除)"
+GW_INPUT_UUID="请输入UUID(输入0删除)"
+GW_INPUT_HOST="请输入本机公网IP(4/6)或域名"
+GW_SHARE_LINK_HINT="你的分享链接是(请勿随意分享给他人):"
+GW_MENU_FW_WAN="配置公网访问防火墙"
+GW_MENU_TG_BOT="配置Telegram专属控制机器人"
+GW_MENU_DDNS="配置DDNS自动域名"
+GW_MENU_VMESS="自定义公网Vmess入站节点"
+GW_MENU_SHADOWSOCKS="自定义公网ShadowSocks入站节点"
+GW_MENU_TS="配置Tailscale内网穿透(限Singbox)"
+GW_MENU_WG="配置Wireguard客户端(限Singbox)"
+GW_FW_STOP_WARN="公网访问防火墙需要先停止服务"
+GW_CONFIRM_CONTINUE="是否确认继续?"
+GW_YES="是"
+GW_NO="否"
+GW_NO_BACK="否,返回上级菜单"
+GW_FW_MANUAL_PORTS="当前手动放行端口:"
+GW_FW_AUTO_PORTS="当前自动放行端口:"
+GW_FW_DEFAULT_BLOCK="默认拦截端口:"
+GW_FW_TOGGLE="启用/关闭公网防火墙:"
+GW_FW_ADD_PORT="添加放行端口(可包含默认拦截端口)"
+GW_FW_REMOVE_PORT="移除指定手动放行端口"
+GW_FW_CLEAR_PORTS="清空全部手动放行端口"
+GW_FW_DISABLE_CONFIRM="是否确认关闭防火墙?"
+GW_FW_DISABLE_RISK="这会带来极大的安全隐患!"
+GW_ERR_DUP_PORT="输入错误!请勿重复添加!"
+GW_ERR_PORT_RANGE="输入错误!请输入正确的数值(1-65535)!"
+GW_ERR_INPUT="输入错误!"
+GW_INPUT_REMOVE_PORT="请直接输入要移除的端口号"
+GW_INPUT_0_BACK="或输入 0 返回上级菜单"
+GW_ERR_PORT_NOT_FOUND="请输入已添加过的端口!"
+GW_TG_CMD_MENU="呼出ShellCrash菜单"
+GW_TG_CMD_HELP="查看帮助"
+GW_TG_WARN="由于网络环境原因,此机器人仅限服务启动时运行!"
+GW_TG_TOGGLE="启用/关闭TG-BOT服务"
+GW_TG_BIND="TG-BOT绑定设置"
+GW_TG_MENUPUSH="启动时推送菜单"
+GW_TG_BIND_FIRST="请先绑定TG-BOT!"
+GW_TG_BOUND_DETECTED="检测到已经绑定了TG推送BOT"
+GW_TG_USE_DIRECT="是否直接使用?"
+GW_INBOUND_WARN_PORT="设置的端口会添加到公网访问防火墙并自动放行!"
+GW_INBOUND_WARN_BASIC="脚本只提供基础功能,更多需求请用自定义配置文件功能!"
+GW_INBOUND_WARN_ILLEGAL="切勿用于搭建违法翻墙节点,违者后果自负!"
+GW_VMS_TOGGLE="启用/关闭Vmess入站"
+GW_SET_LISTEN_PORT="设置监听端口:"
+GW_SET_WSPATH="设置WS-path(可选):"
+GW_SET_UUID="设置密钥-uuid:"
+GW_GEN_RANDOM_KEY="一键生成随机密钥"
+GW_SET_OBFS_HOST="设置混淆host(可选):"
+GW_GEN_SHARE_LINK="一键生成分享链接"
+GW_FILL_REQUIRED="请先完成必选设置!"
+GW_ERR_WSPATH="不是合法的path路径,必须以【/】开头!"
+GW_ERR_UUID="不是合法的UUID格式,请重新输入或使用随机生成功能!"
+GW_INPUT_OBFS_HOST="请输入免流混淆host(输入0删除)"
+GW_SS_TOGGLE="启用/关闭ShadowSocks入站"
+GW_SS_SELECT_CIPHER="请选择要使用的加密协议:"
+GW_SS_SET_PWD="设置password:"
+GW_SS_2022_NOTE_HEADER=" - - - - - - -\033[31m注意\033[0m- - - - - - -"
+GW_SS_2022_REQUIRE=" 2022系列加密必须使用随机生成的password!"
+GW_SS_2022_PASSWORD_ONLY="2022系列加密必须使用脚本随机生成的password!"
+GW_TS_WARN="脚本默认内核为了节约内存没有编译Tailscale模块\n如需使用请先前往自定义内核更新完整版内核文件!"
+GW_TS_KEY_URL="创建密钥:\033[32;4mhttps://login.tailscale.com/admin/settings/keys\033[0m"
+GW_TS_ALLOW_URL="访问非本机目标需允许通告:\033[32;4mhttps://login.tailscale.com\033[0m"
+GW_TS_SUBNET_EXIT_HINT="访问非本机目标需在终端设置使用Subnet或EXIT-NODE模式"
+GW_TS_TOGGLE="启用/关闭Tailscale服务"
+GW_TS_SET_AUTHKEY="设置密钥(Auth Key)"
+GW_TS_SUBNET="通告路由内网地址(Subnet)"
+GW_TS_EXIT_NODE="通告路由全部流量(EXIT-NODE)"
+GW_TS_HOSTNAME="设置设备名称(可选)"
+GW_TS_SET_KEY_FIRST="请先设置密钥!"
+GW_TS_INPUT_KEY="请输入密钥(输入0删除)"
+GW_TS_EXITNODE_WARN="目前exitnode的官方DNS有bug,要么启用域名嗅探并禁用TailscaleDNS,\n要么必须在网页设置Globalname servers为分配的本设备子网IP且启用override"
+GW_TS_INPUT_NAME="请直接输入希望在Tailscale显示的设备名称"
+GW_WG_WARN="脚本默认内核为了节约内存没有编译WireGuard模块\n如需使用请先前往自定义内核更新完整版内核文件!"
+GW_WG_TOGGLE="启用/关闭Wireguard服务"
+GW_WG_SET_ENDPOINT="设置Endpoint地址:"
+GW_WG_SET_ENDPOINT_PORT="设置Endpoint端口:"
+GW_WG_SET_PUBLIC="设置公钥-PublicKey:"
+GW_WG_SET_PRESHARED="设置密钥-PresharedKey:"
+GW_WG_SET_PRIVATE="设置私钥-PrivateKey:"
+GW_WG_SET_IPV4="设置组网IPV4地址:"
+GW_WG_SET_IPV6="可选 组网IPV6地址:"
+GW_INPUT_TEXT_DEL0="请输入相应内容(回车或0删除)"
+GW_INPUT_PLAIN="请输入"
+GW_INPUT_PWD_DEL0="请输入密钥(输入0删除)"
diff --git a/scripts/lang/chs/8_tools.lang b/scripts/lang/chs/8_tools.lang
new file mode 100644
index 00000000..08b432e6
--- /dev/null
+++ b/scripts/lang/chs/8_tools.lang
@@ -0,0 +1,156 @@
+TOOLS_TITLE="工具与优化"
+TOOLS_SSH_DISABLE="禁止"
+TOOLS_SSH_ENABLE="开启"
+TOOLS_ERR_PORT="输入错误!请输入正确的数值(1000-65535)!"
+TOOLS_ERR_PORT_OCCUPIED="当前端口已被其他进程占用,请重新输入!"
+TOOLS_SSH_SET_OK="设置成功,请重新开启外网访问SSH功能!"
+TOOLS_SSH_ENABLED="已开启外网访问SSH功能!"
+TOOLS_SSH_DISABLED="已禁止外网访问SSH!"
+TOOLS_DISABLE="禁用"
+TOOLS_ENABLE="启用"
+TOOLS_CONFIGURED="已配置"
+TOOLS_SSH_ONLY_OPENWRT="此功能仅针对使用Openwrt系统的设备生效,且不依赖服务"
+TOOLS_SSH_UNSUPPORTED_SYSTEM="本功能不支持红米AX6S等镜像化系统设备,请勿尝试!"
+TOOLS_SSH_PORT_ITEM_PREFIX="1) \033[32m修改\033[0m外网访问端口:"
+TOOLS_SSH_PORT_ITEM_SUFFIX=""
+TOOLS_SSH_PASS_ITEM="2) \033[32m修改\033[0mSSH访问密码(请连续输入2次后回车)"
+TOOLS_SSH_TOGGLE_ITEM_PREFIX="3) "
+TOOLS_SSH_TOGGLE_ITEM_SUFFIX="外网访问SSH"
+TOOLS_PROMPT_PORT="请输入端口号(1000-65535)> "
+TOOLS_WARN_COMPAT="本页工具可能无法兼容全部Linux设备,请酌情使用!"
+TOOLS_DISK_USAGE="磁盘占用/所在目录:"
+TOOLS_MENU_TEST_ITEM="1) ShellCrash\033[33m测试菜单\033[0m"
+TOOLS_MENU_GUIDE_ITEM="2) ShellCrash\033[32m新手引导\033[0m"
+TOOLS_MENU_LOG_ITEM="3) \033[36m日志及推送工具\033[0m"
+TOOLS_MENU_SSH_ITEM="4) \033[32m配置\033[0m外网访问SSH"
+TOOLS_MENU_MI_UPDATE_ITEM_PREFIX="5) "
+TOOLS_MENU_MI_UPDATE_ITEM_SUFFIX="小米系统自动更新"
+TOOLS_MENU_MI_AUTO_SSH_ITEM_PREFIX="6) 小米设备软固化SSH —— "
+TOOLS_MENU_MI_AUTO_SSH_ITEM_SUFFIX=""
+TOOLS_MENU_MI_TUN_FIX_ITEM_PREFIX="8) 小米设备Tun模块修复 —— "
+TOOLS_MENU_MI_TUN_FIX_ITEM_SUFFIX=""
+TOOLS_MI_UPDATE_MSG_PREFIX="已"
+TOOLS_MI_UPDATE_MSG_SUFFIX="小米路由器的自动更新,如未生效,请在官方APP中同步设置!"
+TOOLS_UNSUPPORTED_DEVICE="不支持的设备!"
+TOOLS_FETCHING_SCRIPT="正在获取在线脚本......"
+TOOLS_DOWNLOAD_FAIL="文件下载失败!"
+TOOLS_DISABLE_FIX_CONFIRM="是否禁用此功能并移除相关补丁?"
+TOOLS_YES="1) 是"
+TOOLS_NO_BACK="0) 否,返回上级菜单"
+TOOLS_NO="0) 否"
+TOOLS_SELECT_PROMPT="请输入对应标号> "
+TOOLS_PATCH_REMOVED="补丁文件已移除,请立即重启设备以防止出错!"
+TOOLS_TUN_WARN1="本功能需要修改系统文件,不保证没有任何风险!"
+TOOLS_TUN_WARN2="本功能采集的Tun模块并不一定适用于你的设备!"
+TOOLS_ACCEPT_RISK="1) 我已知晓,出现问题会自行承担!"
+TOOLS_TUN_CONNECTING="正在连接服务器获取Tun模块补丁文件......"
+TOOLS_TUN_OK="设置成功!请重启服务!"
+TOOLS_TUN_FAIL="文件下载失败,请重试!"
+TOOLS_DEVICE_NOT_NEED="当前设备无需设置,请勿尝试!"
+TOOLS_AUTO_SSH_WARN1="本功能使用软件命令进行固化不保证100%成功!"
+TOOLS_AUTO_SSH_WARN2="如有问题请加群反馈:"
+TOOLS_AUTO_SSH_PWD_HINT1="请输入需要还原的SSH密码(不影响当前密码)"
+TOOLS_AUTO_SSH_PWD_HINT2="(回车可跳过)"
+TOOLS_AUTO_SSH_INPUT="请输入> "
+TOOLS_LOG_TG_PREFIX="1) Telegram推送\t——"
+TOOLS_LOG_TG_SUFFIX=""
+TOOLS_LOG_DEER_PREFIX="2) PushDeer推送\t——"
+TOOLS_LOG_DEER_SUFFIX=""
+TOOLS_LOG_BARK_PREFIX="3) Bark推送-IOS\t——"
+TOOLS_LOG_BARK_SUFFIX=""
+TOOLS_LOG_PO_PREFIX="4) Passover推送\t——"
+TOOLS_LOG_PO_SUFFIX=""
+TOOLS_LOG_PP_PREFIX="5) PushPlus推送\t——"
+TOOLS_LOG_PP_SUFFIX=""
+TOOLS_LOG_SYNO_PREFIX="6) SynoChat推送\t——"
+TOOLS_LOG_SYNO_SUFFIX=""
+TOOLS_LOG_GOTIFY_PREFIX="7) Gotify推送\t ——"
+TOOLS_LOG_GOTIFY_SUFFIX=""
+TOOLS_LOG_VIEW="a) 查看\033[36m运行日志\033[0m"
+TOOLS_LOG_TASK_PREFIX="b) 推送任务日志\t——"
+TOOLS_LOG_TASK_SUFFIX=""
+TOOLS_LOG_DEVICE_PREFIX="c) 设置设备名称\t——"
+TOOLS_LOG_DEVICE_SUFFIX=""
+TOOLS_LOG_CLEAR="d) 清空日志文件"
+TOOLS_CONFIRM_CLOSE_TG="是否确认关闭TG日志推送?"
+TOOLS_CONFIRM_CLOSE_DEER="是否确认关闭PushDeer日志推送?"
+TOOLS_CONFIRM_CLOSE_BARK="是否确认关闭Bark日志推送?"
+TOOLS_CONFIRM_CLOSE_PO="是否确认关闭Pushover日志推送?"
+TOOLS_CONFIRM_CLOSE_PP="是否确认关闭PushPlus日志推送?"
+TOOLS_CONFIRM_CLOSE_SYNO="是否确认关闭SynoChat日志推送?"
+TOOLS_CONFIRM_CLOSE_GOTIFY="是否确认关闭Gotify日志推送?"
+TOOLS_BOT_PUBLIC="1) 使用公共机器人\t——不依赖内核服务"
+TOOLS_BOT_PRIVATE="2) 使用私人机器人\t——需要额外申请"
+TOOLS_PUSHDEER_SELECT_SERVER="请选择PushDeer服务器类型:"
+TOOLS_PUSHDEER_OFFICIAL="1) 官方服务器(api2.pushdeer.com)"
+TOOLS_PUSHDEER_CUSTOM="2) 自建服务器"
+TOOLS_PUSHDEER_CUSTOM_URL_HINT="请输入自建PushDeer服务器地址(不含/message/push)"
+TOOLS_PUSHDEER_CUSTOM_URL_EXAMPLE="例如:\033[36mhttps://push.example.com\033[0m"
+TOOLS_PUSHDEER_CUSTOM_URL_INPUT="请直接输入服务器地址"
+TOOLS_OR_BACK="或输入 0 返回上级菜单"
+TOOLS_PUSHDEER_INSTALL1="1. 请先前往 \033[32;4mhttp://www.pushdeer.com/official.html\033[0m 扫码安装快应用或下载APP"
+TOOLS_PUSHDEER_INSTALL2="2. 打开快应用/APP,并完成登陆"
+TOOLS_PUSHDEER_INSTALL3="3. \033[33m切换到「设备」标签页,点击右上角的加号,注册当前设备\033[0m"
+TOOLS_PUSHDEER_INSTALL4="4. \033[36m切换到「秘钥」标签页,点击右上角的加号,创建一个秘钥,并复制\033[0m"
+TOOLS_PUSHDEER_SECRET_HINT="请直接输入你复制的秘钥"
+TOOLS_PUSHDEER_OK="已完成PushDeer日志推送设置!"
+TOOLS_BARK_WARN="Bark推送仅支持IOS系统,其他平台请使用其他推送方式!"
+TOOLS_BARK_INSTALL="请安装Bark-IOS客户端,并在客户端中找到专属推送链接"
+TOOLS_BARK_URL_HINT="请直接输入你的Bark推送链接"
+TOOLS_BARK_OK="已完成Bark日志推送设置!"
+TOOLS_PUSHOVER_REG="请先通过 \033[32;4mhttps://pushover.net/\033[0m 注册账号并获取\033[36mUser Key\033[0m"
+TOOLS_PUSHOVER_USERKEY_HINT="请直接请输入你的User Key"
+TOOLS_PUSHOVER_VERIFY="请检查注册邮箱,完成账户验证"
+TOOLS_PUSHOVER_VERIFIED="我已经验证完成"
+TOOLS_PUSHOVER_VERIFY_PROMPT="我已经验证完成(1/0)> "
+TOOLS_PUSHOVER_TOKEN_BUILD="请通过 \033[32;4mhttps://pushover.net/apps/build\033[0m 生成\033[36mAPI Token\033[0m"
+TOOLS_PUSHOVER_TOKEN_HINT="请输入你的API Token"
+TOOLS_PUSHOVER_OK="已完成Passover日志推送设置!"
+TOOLS_PUSHPLUS_REG="请先通过 \033[32;4mhttps://www.pushplus.plus/push1.html\033[0m 注册账号并获取\033[36mtoken\033[0m"
+TOOLS_PUSHPLUS_TOKEN_HINT="请直接输入你的token"
+TOOLS_PUSHPLUS_OK="已完成PushPlus日志推送设置!"
+TOOLS_SYNOCHAT_URL_HINT="请输入你的Synology DSM主页地址"
+TOOLS_SYNOCHAT_TOKEN_HINT="请输入你的Synology Chat Token"
+TOOLS_SYNOCHAT_USERID_HINT="请通过\"你的群晖地址/webapi/entry.cgi?api=SYNO.Chat.External&method=user_list&version=2&token=你的TOKEN\"获取user_id"
+TOOLS_SYNOCHAT_USERID_INPUT="请输入你的user_id> "
+TOOLS_SYNOCHAT_OK="已完成SynoChat日志推送设置!"
+TOOLS_GOTIFY_REG="请先通过Gotify服务器获取推送URL"
+TOOLS_GOTIFY_FORMAT="格式示例: https://gotify.example.com/message?token=你的应用令牌"
+TOOLS_GOTIFY_URL_HINT="请直接你的Gotify推送URL"
+TOOLS_LOG_NOT_FOUND="未找到相关日志!"
+TOOLS_DEVICE_NAME_HINT="请直接输入本设备自定义推送名称"
+TOOLS_DEVICE_NAME_BACK="或直接回车确认返回上级菜单"
+TOOLS_LOG_CLEARED="运行日志及任务日志均已清空!"
+TOOLS_TEST_MENU_TITLE="这里是测试命令菜单"
+TOOLS_TEST_MENU_HINT="如遇问题尽量运行相应命令后截图提交issue或TG讨论组"
+TOOLS_TEST_ITEM_1="1) Debug模式运行内核"
+TOOLS_TEST_ITEM_2="2) 查看系统DNS端口(:53)占用 "
+TOOLS_TEST_ITEM_3="3) 测试ssl加密(aes-128-gcm)跑分"
+TOOLS_TEST_ITEM_4="4) 查看ShellCrash相关路由规则"
+TOOLS_TEST_ITEM_5="5) 查看内核配置文件前40行"
+TOOLS_TEST_ITEM_6="6) 测试代理服务器连通性(google.tw)"
+TOOLS_NETSTAT_HINT="可以使用\033[44m netstat -ntulp |grep xxx \033[0m来查询任意(xxx)端口"
+TOOLS_FW_TITLE="----------------本机防火墙---------------------"
+TOOLS_PROXY_NOTE="注意:依赖curl(不支持wget),且测试结果不保证一定准确!"
+TOOLS_PROXY_OK="连接成功!响应时间为:"
+TOOLS_PROXY_TIMEOUT="连接超时!请重试或检查节点配置!"
+TOOLS_DEBUG_WARN1="注意:Debug运行均会停止原本的内核服务"
+TOOLS_DEBUG_WARN2_PREFIX="后台运行日志地址:"
+TOOLS_DEBUG_WARN2_SUFFIX=""
+TOOLS_DEBUG_WARN3="如长时间运行后台监测,日志等级推荐error!防止文件过大!"
+TOOLS_DEBUG_WARN4="你亦可通过:\033[33mcrash -s debug 'warning'\033[0m命令使用其他日志等级"
+TOOLS_DEBUG_ITEM_1_PREFIX="1) 仅测试"
+TOOLS_DEBUG_ITEM_1_SUFFIX="配置文件可用性"
+TOOLS_DEBUG_ITEM_2_PREFIX="2) 前台运行"
+TOOLS_DEBUG_ITEM_2_SUFFIX="配置文件,不配置防火墙劫持(使用Ctrl+C手动停止)"
+TOOLS_DEBUG_ITEM_3="3) 后台运行完整启动流程并配置防火墙劫持,日志等级:\033[31merror\033[0m"
+TOOLS_DEBUG_ITEM_4="4) 后台运行完整启动流程并配置防火墙劫持,日志等级:\033[32minfo\033[0m"
+TOOLS_DEBUG_ITEM_5="5) 后台运行完整启动流程并配置防火墙劫持,日志等级:\033[33mdebug\033[0m"
+TOOLS_DEBUG_ITEM_6_PREFIX="6) 后台运行完整启动流程并配置防火墙劫持,且将错误日志打印到闪存:"
+TOOLS_DEBUG_ITEM_6_SUFFIX=""
+TOOLS_DEBUG_ITEM_8="8) 后台运行完整启动流程,输出执行错误并查找上下文,之后关闭进程"
+TOOLS_DEBUG_ITEM_9_PREFIX="9) 将"
+TOOLS_DEBUG_ITEM_9_SUFFIX="下json文件合并为"
+TOOLS_FLASH_WARN="频繁写入闪存会导致闪存寿命降低,如非遇到会导致设备死机或重启的bug,请勿使用此功能!"
+TOOLS_FLASH_CONFIRM="是否确认启用此功能?"
+TOOLS_MERGE_OK="合并成功!"
diff --git a/scripts/lang/chs/9_upgrade.lang b/scripts/lang/chs/9_upgrade.lang
new file mode 100644
index 00000000..de986d3c
--- /dev/null
+++ b/scripts/lang/chs/9_upgrade.lang
@@ -0,0 +1,296 @@
+UPG_ERR_TRY_OTHER_SOURCE="请尝试切换至其他安装源后重新下载!"
+UPG_ERR_LOCAL_INSTALL="或者参考 \033[32;4mhttps://juewuy.github.io/bdaz\033[0m 进行本地安装!"
+UPG_TITLE="更新与支持"
+UPG_CUR_DIR_SPACE="当前目录"
+UPG_LOW_SPACE_HINT="当前目录剩余空间较低,建议开启小闪存模式!"
+UPG_MENU_SCRIPT="更新"
+UPG_MENU_SCRIPT_NAME="管理脚本"
+UPG_MENU_CORE="切换/更新"
+UPG_MENU_CORE_NAME="内核文件"
+UPG_MENU_GEO="安装/更新本地"
+UPG_MENU_GEO_NAME="数据库文件"
+UPG_MENU_DB="安装/更新本地"
+UPG_MENU_DB_NAME="Dashboard面板"
+UPG_MENU_CRT="安装/更新本地"
+UPG_MENU_CRT_NAME="根证书文件"
+UPG_MENU_PAC="自动代理查看"
+UPG_MENU_SOURCE="切换"
+UPG_MENU_SOURCE_NAME="安装源及版本分支"
+UPG_MENU_UNINSTALL="卸载ShellCrash"
+UPG_MENU_THANKS="感谢列表!"
+UPG_PAC_LINK="PAC配置链接为:"
+UPG_PAC_GUIDE="PAC的使用教程请参考:"
+UPG_THANKS_TITLE="感谢以下项目及其开发者们的无私奉献!"
+UPG_THANKS_SPECIAL="特别感谢:\033[36m所有帮助及赞助过此项目的同仁们!\033[0m"
+UPG_CHECKING="正在检查更新......"
+UPG_CHECK_OK="检查更新成功"
+UPG_CHECK_FAIL="检查更新失败!请尝试切换其他安装源!"
+UPG_DOWNLOAD_FAIL="文件下载失败!"
+UPG_EXTRACTING="开始解压文件......"
+UPG_EXTRACT_FAIL="文件解压失败!"
+UPG_SCRIPT_OK="脚本更新成功!"
+UPG_SCRIPT_WARN="注意:更新时会停止服务!"
+UPG_SCRIPT_CUR_VER="当前脚本版本为:"
+UPG_SCRIPT_NEW_VER="最新脚本版本为:"
+UPG_UPDATE_NOW="立即更新"
+UPG_SCRIPT_MGR_OK="管理脚本更新成功!"
+UPG_CPUCORE_HINT1="仅适合脚本无法正确识别核心或核心无法正常运行时使用!"
+UPG_CPUCORE_HINT2="不知道如何获取核心版本?"
+UPG_CPUCORE_HINT3="请参考:"
+UPG_CPUCORE_LIST="当前可供在线下载的处理器架构为:"
+UPG_CPUCORE_ERR="请输入正确的处理器架构!"
+UPG_CORETYPE_CONFIRM="请确认该自定义内核的类型:"
+UPG_CORE_SWITCH_PREFIX="已从"
+UPG_CORE_SWITCH_MID="内核切换至"
+UPG_CORE_SWITCH_SUFFIX="内核"
+UPG_CORE_SWITCH_WARN="二者Geo数据库及yaml/json配置文件不通用"
+UPG_CORE_SWITCH_KEEP="是否保留相关数据库文件?"
+UPG_KEEP="保留"
+UPG_NOT_KEEP="不保留"
+UPG_PAC_LINK_TEXT="PAC配置链接为:"
+UPG_PAC_GUIDE_TEXT="PAC的使用教程请参考:"
+UPG_THANKS_PROJECTS="感谢以下项目及其开发者们的无私奉献!"
+UPG_THANKS_SPECIAL_TEXT="特别感谢:\033[36m所有帮助及赞助过此项目的同仁们!\033[0m"
+UPG_GETTING_UPDATE="正在检查更新......"
+UPG_SCRIPT_CUR_VER_TEXT="当前脚本版本为:"
+UPG_SCRIPT_NEW_VER_TEXT="最新脚本版本为:"
+UPG_UPDATE_NOW_TEXT="立即更新"
+UPG_CPUCORE_HINT1_TEXT="仅适合脚本无法正确识别核心或核心无法正常运行时使用!"
+UPG_CPUCORE_HINT2_TEXT="不知道如何获取核心版本?"
+UPG_CPUCORE_HINT3_TEXT="请参考:"
+UPG_CPUCORE_LIST_TEXT="当前可供在线下载的处理器架构为:"
+UPG_CORETYPE_CONFIRM_TEXT="请确认该自定义内核的类型:"
+UPG_CORE_SWITCH_KEEP_TEXT="是否保留相关数据库文件?"
+UPG_KEEP_TEXT="保留"
+UPG_NOT_KEEP_TEXT="不保留"
+UPG_GETTING_CORE_TEXT_PREFIX="正在在线获取"
+UPG_GETTING_CORE_TEXT_SUFFIX="核心文件......"
+UPG_CORE_DOWNLOAD_OK_TEXT_PREFIX=""
+UPG_CORE_DOWNLOAD_OK_TEXT_SUFFIX="核心下载成功!"
+UPG_CORE_DOWNLOAD_FAIL_TEXT="核心文件下载失败!"
+UPG_CORE_DOWNLOAD_VERIFY_FAIL_TEXT="核心文件下载成功但校验失败"
+UPG_CORE_DOWNLOAD_VERIFY_HINT_TEXT="请尝试手动指定CPU版本"
+UPG_CORE_LINK_TEXT="正在获取内核文件链接......"
+UPG_CORE_INFO_TITLE="内核版本:"
+UPG_CORE_INFO_TIME1="发布时间:"
+UPG_CORE_INFO_TIME2="更新时间:"
+UPG_CORE_INFO_SELECT="请确认内核信息并选择:"
+UPG_CORE_NOT_FOUND="找不到可用内核,可能是开发者没有编译相关CPU架构版本的内核文件!"
+UPG_CORE_CHECK_FAIL_HINT="查找失败,请尽量在服务启动后再使用本功能!"
+UPG_CUSTOM_CORE_SOURCE="此处内核通常源自互联网采集,此处致谢各位开发者!"
+UPG_CUSTOM_CORE_WARN="自定义内核未经过完整适配,使用出现问题请自行解决!"
+UPG_CUSTOM_CORE_TASK_WARN="自定义内核已适配定时任务,但不支持小闪存模式!"
+UPG_CUSTOM_CORE_NET_WARN="如遇到网络错误请先启动ShellCrash服务!"
+UPG_CUSTOM_CORE_CURRENT="当前内核为:"
+UPG_CUSTOM_CORE_SELECT="请选择需要使用的核心:"
+UPG_CUSTOM_CORE_MENU_OFFICIAL="版本官方内核"
+UPG_CUSTOM_CORE_MENU_ALPHA="版本内核(支持Smart策略)"
+UPG_CUSTOM_CORE_MENU_MULTI="多版本内核"
+UPG_CUSTOM_CORE_LINK_HINT="请输入自定义内核的链接地址"
+UPG_CUSTOM_CORE_LINK_HINT2="(必须是以.tar.gz、.upx或.gz结尾的压缩文件)"
+UPG_CUSTOM_CORE_LINK_HINT3="或者输入 0 返回上级菜单"
+UPG_CUSTOM_CORE_LINK_MENU="使用自定义内核链接"
+UPG_ZIPTYPE_TITLE="请选择内核分支及压缩方式:"
+UPG_ZIPTYPE_1="1) \033[36m最简编译release版本,upx压缩\033[0m"
+UPG_ZIPTYPE_1_HINT="不支持Gvisor、Tailscale、Wireguard、NaiveProxy"
+UPG_ZIPTYPE_2="2) \033[32m标准编译release版本,tar.gz压缩\033[0m"
+UPG_ZIPTYPE_2_HINT="完整支持脚本全部内置功能"
+UPG_ZIPTYPE_3="3) \033[33m完整编译alpha版本,gz压缩\033[0m"
+UPG_ZIPTYPE_3_HINT="占用可能略高,稳定性自测"
+UPG_CORE_MENU_CURRENT="当前内核:"
+UPG_CORE_MENU_SYS="当前系统处理器架构:"
+UPG_CORE_MENU_LOCAL_HINT="如需本地上传,请将.upx .gz .tar.gz文件上传至 /tmp 目录后重新运行crash命令"
+UPG_CORE_MENU_SELECT="请选择需要使用的核心版本:"
+UPG_CORE_MENU_1_PREFIX="1) \033[43;30mMihomo\033[0m:\033[32m"
+UPG_CORE_MENU_1_SUFFIX=" \033[32m(原meta内核)支持全面\033[0m \033[33m占用略高\033[0m"
+UPG_CORE_MENU_2_PREFIX="2) \033[43;30mSingBoxR\033[0m:\033[32m"
+UPG_CORE_MENU_2_SUFFIX=" \033[32m支持全面\033[0m \033[33m使用reF1nd增强分支\033[0m"
+UPG_CORE_MENU_3_PREFIX="3) \033[43;30mSingBox\033[0m:\033[32m"
+UPG_CORE_MENU_3_SUFFIX=" \033[32m占用较低\033[0m \033[33m不支持providers\033[0m"
+UPG_CORE_MENU_4_PREFIX="4) \033[43;30mClash\033[0m:\033[32m"
+UPG_CORE_MENU_4_SUFFIX=" \033[32m占用低\033[0m \033[33m不安全,已停止维护\033[0m"
+UPG_CORE_MENU_5_PREFIX="5) 切换版本分支及压缩方式:\033[32m"
+UPG_CORE_MENU_5_SUFFIX="\033[0m"
+UPG_CORE_MENU_6_PREFIX="6) \033[36m使用自定义内核\033[0m "
+UPG_CORE_MENU_6_SUFFIX=""
+UPG_CORE_MENU_7="7) \033[32m更新当前内核\033[0m"
+UPG_CORE_MENU_9="9) 手动指定处理器架构"
+UPG_GEO_GETTING="正在从服务器获取数据库文件......"
+UPG_GEO_OK_PREFIX=""
+UPG_GEO_OK_SUFFIX="数据库文件下载成功!"
+UPG_GEO_LINKING="正在获取数据库文件......"
+UPG_GEO_FINDING="正在查找可更新的数据库文件......"
+UPG_GEO_SELECT="请选择需要更新的数据库文件:"
+UPG_GEO_NO_RESULT="查找失败,请尽量在服务启动后再使用本功能!"
+UPG_GEO_CUSTOM_HINT="此处数据库均源自互联网采集,此处致谢各位开发者!"
+UPG_GEO_CUSTOM_HINT2="请点击或复制链接前往项目页面查看具体说明!"
+UPG_GEO_CUSTOM_HINT3="自定义数据库不支持定时任务及小闪存模式!"
+UPG_GEO_CUSTOM_HINT4="如遇到网络错误请先启动ShellCrash服务!"
+UPG_GEO_SOURCE_SELECT="请选择需要更新的数据库项目来源:"
+UPG_GEO_LOCAL_ONLY1="(仅限Clash/Mihomo)"
+UPG_GEO_LOCAL_ONLY2="(仅限SingBox-srs)"
+UPG_GEO_LOCAL_ONLY3="(仅限Mihomo-mrs)"
+UPG_GEO_LOCAL_ONLY4="(仅限Clash-GeoIP)"
+UPG_GEO_CUSTOM_LINK="自定义数据库链接"
+UPG_GEO_CLEAN_HINT1_PREFIX="这将清理"
+UPG_GEO_CLEAN_HINT1_SUFFIX="目录及/ruleset目录下所有数据库文件!"
+UPG_GEO_CLEAN_HINT2="清理后启动服务即可自动下载所需文件"
+UPG_GEO_CLEAN_CONFIRM="确认清理"
+UPG_GEO_CLEAN_OK="所有数据库文件均已清理!"
+UPG_DB_GETTING="正在连接服务器获取安装文件......"
+UPG_DB_DOWNLOAD_OK="下载成功,正在解压文件......"
+UPG_DB_OK="面板安装成功!"
+UPG_DB_REFRESH_HINT="如未生效,请使用【Ctrl+F5】强制刷新浏览器!"
+UPG_DB_INSTALLED="检测到已经安装过本地面板"
+UPG_DB_UPGRADE="升级/覆盖安装"
+UPG_DB_CANCEL="安装已取消"
+UPG_DB_DIR_SELECT="请选择面板安装目录:"
+UPG_DB_DIR_1_PREFIX="1) 在"
+UPG_DB_DIR_1_SUFFIX="/ui目录安装"
+UPG_DB_DIR_2="2) 在/www/clash目录安装"
+UPG_DB_TITLE="安装 dashboard 管理面板到本地"
+UPG_DB_TITLE2="打开管理面板的速度更快且更稳定"
+UPG_DB_SELECT="请选择面板安装类型:"
+UPG_DB_WIP=" - - - - - - -维护中- - - - - - -"
+UPG_DB_OLD=" - - - - - -已停止维护- - - - - -"
+UPG_DB_INSTALL_1="1) 安装\033[32mzashboard面板\033[0m(约2.2mb)"
+UPG_DB_INSTALL_2="2) 安装\033[32mMetaXD面板\033[0m(约1.5mb)"
+UPG_DB_INSTALL_3="3) 安装\033[32mYacd-Meta魔改面板\033[0m(约1.7mb)"
+UPG_DB_INSTALL_4="4) 安装\033[32m基础面板\033[0m(约500kb)"
+UPG_DB_INSTALL_5="5) 安装\033[32mMeta基础面板\033[0m(约800kb)"
+UPG_DB_INSTALL_6="6) 安装\033[32mYacd面板\033[0m(约1.1mb)"
+UPG_DB_UNINSTALL="9) \033[31m卸载本地面板\033[0m"
+UPG_DB_UNINSTALL_CONFIRM="是否卸载本地面板?"
+UPG_DB_UNINSTALL_YES="1) 确认卸载"
+UPG_DB_UNINSTALL_OK="面板已经卸载!"
+UPG_CRT_DB_OK="证书安装成功!"
+UPG_CRT_TITLE1="安装/更新本地根证书文件(ca-certificates.crt)"
+UPG_CRT_TITLE2="用于解决证书校验错误,x509报错等问题"
+UPG_CRT_TITLE3="无上述问题的设备请勿使用!"
+UPG_CRT_EXISTS="检测到系统已经存在根证书文件:"
+UPG_CRT_UPDATE="1) 覆盖更新"
+UPG_CRT_INSTALL="1) 立即安装"
+UPG_CRT_BACK="0) 返回上级菜单"
+UPG_CRT_WARN="设备可能尚未安装openssl,无法安装证书文件!"
+UPG_SOURCE_CUR="当前版本:"
+UPG_SOURCE_CUR2="当前源:"
+UPG_SOURCE_TITLE="切换ShellCrash版本及更新源地址"
+UPG_SOURCE_SWITCH_STABLE="a) 切换至\033[32m稳定版-stable\033[0m"
+UPG_SOURCE_SWITCH_MASTER="b) 切换至\033[36m公测版-master\033[0m"
+UPG_SOURCE_SWITCH_DEV="c) 切换至\033[33m开发版-dev\033[0m"
+UPG_SOURCE_CUSTOM="d) 自定义源地址(用于本地源或自建源)"
+UPG_SOURCE_ROLLBACK="e) \033[31m版本回退\033[0m"
+UPG_SOURCE_DEV_WARN1="开发版未经过妥善测试,可能依然存在大量bug!!!"
+UPG_SOURCE_DEV_WARN2="如果你没有足够的耐心或者测试经验,切勿使用此版本!"
+UPG_SOURCE_DEV_WARN3="请务必加入我们的讨论组:\033[36;4mhttps://t.me/ShellClash\033[0m"
+UPG_SOURCE_DEV_CONFIRM="是否依然切换到开发版?"
+UPG_SOURCE_DEV_YES="1) 确认切换"
+UPG_SOURCE_CUSTOM_HINT="请直接输入个人源路径"
+UPG_SOURCE_CUSTOM_HINT2="或者输入 0 返回上级菜单"
+UPG_SOURCE_CUSTOM_INPUT="请输入个人源路径> "
+UPG_SOURCE_VER_GETTING="正在获取版本信息......"
+UPG_SOURCE_VER_OK="获取版本信息成功"
+UPG_SOURCE_ROLLBACK_SELECT="请选择想要回退至的具体版本:"
+UPG_SOURCE_ROLLBACK_FAIL="版本回退信息获取失败,请尝试更换其他安装源!"
+UPG_SOURCE_ROLLBACK_NOTSUP="当前源不支持版本回退"
+UPG_SOURCE_ROLLBACK_HINT="请尝试更换其他安装源!"
+UPG_THANKS_ITEM_CLASH="Clash 开发:Dreamacro"
+UPG_THANKS_ITEM_SINGBOX="sing-box 开发:SagerNet"
+UPG_THANKS_ITEM_SINGBOX_URL="项目地址:https://github.com/SagerNet/sing-box"
+UPG_THANKS_ITEM_METACUBE="MetaCubeX 开发:MetaCubeX"
+UPG_THANKS_ITEM_METACUBE_URL="项目地址:https://github.com/MetaCubeX"
+UPG_THANKS_ITEM_YACD="YACD面板 开发:haishanh"
+UPG_THANKS_ITEM_YACD_URL="项目地址:https://github.com/haishanh/yacd"
+UPG_THANKS_ITEM_ZASH="Zashboard 开发:Zephyruso"
+UPG_THANKS_ITEM_ZASH_URL="项目地址:https://github.com/Zephyruso/zashboard"
+UPG_THANKS_ITEM_SUB="Subconverter 开发:tindy2013"
+UPG_THANKS_ITEM_SUB_URL="项目地址:https://github.com/tindy2013/subconverter"
+UPG_THANKS_ITEM_REF1ND="sing-box-reF1nd 开发:reF1nd"
+UPG_THANKS_ITEM_REF1ND_URL="项目地址:https://github.com/reF1nd/sing-box"
+UPG_THANKS_ITEM_DUSTIN="DustinWin 开发:DustinWin"
+UPG_THANKS_ITEM_DUSTIN_URL="开发者地址:https://github.com/DustinWin"
+UPG_CORE_GET_LINK_TITLE="正在获取内核文件链接......"
+UPG_CUSTOM_CORE_NOTE1="不支持Gvisor、Tailscale、Wireguard、NaiveProxy"
+UPG_CORE_V1_PREFIX="1) \033[43;30mMihomo\033[0m:\033[32m"
+UPG_CORE_V1_SUFFIX=" \033[32m(原meta内核)支持全面\033[0m \033[33m占用略高\033[0m"
+UPG_CORE_V1_DOC="说明文档:\033[36;4mhttps://wiki.metacubex.one\033[0m"
+UPG_CORE_V2_PREFIX="2) \033[43;30mSingBoxR\033[0m:\033[32m"
+UPG_CORE_V2_SUFFIX=" \033[32m支持全面\033[0m \033[33m使用reF1nd增强分支\033[0m"
+UPG_CORE_V2_DOC="说明文档:\033[36;4mhttps://sing-boxr.dustinwin.cc.cd\033[0m"
+UPG_CORE_V3_PREFIX="3) \033[43;30mSingBox\033[0m:\033[32m"
+UPG_CORE_V3_SUFFIX=" \033[32m占用较低\033[0m \033[33m不支持providers\033[0m"
+UPG_CORE_V3_DOC="说明文档:\033[36;4mhttps://sing-box.sagernet.org\033[0m"
+UPG_CORE_V4_PREFIX="4) \033[43;30mClash\033[0m:\033[32m"
+UPG_CORE_V4_SUFFIX=" \033[32m占用低\033[0m \033[33m不安全,已停止维护\033[0m"
+UPG_CORE_V4_DOC="说明文档:\033[36;4mhttps://lancellc.gitbook.io\033[0m"
+UPG_CORE_ASUS_WARN="Meta内核使用的GeoSite.dat数据库在华硕设备存在被系统误删的问题,可能无法使用!"
+UPG_GEO_FIND_TITLE="正在查找可更新的数据库文件......"
+UPG_GEO_SOURCE_TITLE="请选择需要更新的数据库项目来源:"
+UPG_GEO_LINK_HINT="请输入自定义数据库的链接地址> "
+UPG_GEO_CHOOSE_HINT="注意:Mihomo内核和SingBox内核的数据库文件不通用"
+UPG_GEO_LATEST="在线数据库最新版本(每日同步上游):"
+UPG_GEO_CHOOSE="请选择需要更新的Geo数据库文件:"
+UPG_GEO_ITEM1="1) CN-IP绕过文件(约0.1mb)"
+UPG_GEO_ITEM2="2) CN-IPV6绕过文件(约30kb)"
+UPG_GEO_ITEM3="3) Mihomo精简版GeoIP_cn数据库(约0.1mb)"
+UPG_GEO_ITEM4="4) Mihomo完整版GeoSite数据库(约5mb)"
+UPG_GEO_ITEM5="5) Mihomo-mrs数据库常用包(约1mb,非必要勿用)"
+UPG_GEO_ITEM6="6) Singbox-srs数据库常用包(约0.8mb,非必要勿用)"
+UPG_GEO_ITEM8="8) \033[36m自定义数据库文件\033[0m"
+UPG_GEO_ITEM9="9) \033[31m清理数据库文件\033[0m"
+UPG_GEO_CLEAN_PROMPT="确认清理"
+UPG_GEO_CLEAN_WARN_PREFIX="这将清理"
+UPG_GEO_CLEAN_WARN_SUFFIX="目录及/ruleset目录下所有数据库文件!"
+UPG_GEO_CLEAN_WARN2="清理后启动服务即可自动下载所需文件"
+UPG_GEO_CLEANED="所有数据库文件均已清理!"
+UPG_DB_CONNECTING="正在连接服务器获取安装文件......"
+UPG_DB_INSTALLED_HINT="检测到已经安装过本地面板"
+UPG_DB_INSTALL_CANCEL="安装已取消"
+UPG_DB_DIR_TITLE="请选择面板安装目录:"
+UPG_DB_DIR_1_TEXT_PREFIX="1) 在"
+UPG_DB_DIR_1_TEXT_SUFFIX="/ui目录安装"
+UPG_DB_DIR_2_TEXT="2) 在/www/clash目录安装"
+UPG_DB_INSTALL_TITLE="安装 dashboard 管理面板到本地"
+UPG_DB_INSTALL_TITLE2="打开管理面板的速度更快且更稳定"
+UPG_DB_INSTALL_SELECT="请选择面板安装类型:"
+UPG_DB_INSTALL_MID=" - - - - - - -维护中- - - - - - -"
+UPG_DB_INSTALL_END=" - - - - - -已停止维护- - - - - -"
+UPG_DB_INSTALL_4_TEXT="4) 安装\033[32m基础面板\033[0m(约500kb)"
+UPG_DB_INSTALL_5_TEXT="5) 安装\033[32mMeta基础面板\033[0m(约800kb)"
+UPG_DB_INSTALL_6_TEXT="6) 安装\033[32mYacd面板\033[0m(约1.1mb)"
+UPG_DB_UNINSTALL_PROMPT="是否卸载本地面板?"
+UPG_DB_UNINSTALL_CONFIRM_TEXT="1) 确认卸载"
+UPG_DB_UNINSTALLED="面板已经卸载!"
+UPG_CRT_CONNECTING="正在连接服务器获取安装文件......"
+UPG_CRT_INSTALL_TITLE1="安装/更新本地根证书文件(ca-certificates.crt)"
+UPG_CRT_INSTALL_TITLE2="用于解决证书校验错误,x509报错等问题"
+UPG_CRT_INSTALL_TITLE3="无上述问题的设备请勿使用!"
+UPG_CRT_EXIST_HINT="检测到系统已经存在根证书文件:"
+UPG_CRT_OVERWRITE="1) 覆盖更新"
+UPG_CRT_NOW="1) 立即安装"
+UPG_CRT_NOT_USE="设备可能尚未安装openssl,无法安装证书文件!"
+UPG_SOURCE_TITLE2="切换ShellCrash版本及更新源地址"
+UPG_SOURCE_CUR_VER="当前版本:"
+UPG_SOURCE_CUR_URL="当前源:"
+UPG_SOURCE_STABLE_TEXT="稳定版"
+UPG_SOURCE_MASTER_TEXT="公测版"
+UPG_SOURCE_DEV_TEXT="开发版"
+UPG_SOURCE_DEV_WARN4="开发版未经过妥善测试,可能依然存在大量bug!!!"
+UPG_SOURCE_DEV_WARN5="如果你没有足够的耐心或者测试经验,切勿使用此版本!"
+UPG_SOURCE_DEV_WARN6="请务必加入我们的讨论组:\033[36;4mhttps://t.me/ShellClash\033[0m"
+UPG_SOURCE_DEV_ASK="是否依然切换到开发版?"
+UPG_SOURCE_DEV_CONFIRM_TEXT="1) 确认切换"
+UPG_SOURCE_PATH_HINT="请直接输入个人源路径"
+UPG_SOURCE_PATH_HINT2="或者输入 0 返回上级菜单"
+UPG_SOURCE_PATH_INPUT="请输入个人源路径> "
+UPG_SOURCE_GETTING_VER="正在获取版本信息......"
+UPG_SOURCE_GET_VER_OK="获取版本信息成功"
+UPG_SOURCE_ROLLBACK_SELECT_TEXT="请选择想要回退至的具体版本:"
+UPG_SOURCE_ROLLBACK_FAIL_TEXT="版本回退信息获取失败,请尝试更换其他安装源!"
+UPG_SOURCE_ROLLBACK_NOTSUP_TEXT="当前源不支持版本回退"
+UPG_SOURCE_ROLLBACK_HINT_TEXT="请尝试更换其他安装源!"
+UPG_SOURCE_SWITCH_OK="源地址切换成功!"
+UPG_GEO_TYPE_LITE="精简版"
+UPG_GEO_TYPE_FULL="全球版"
+UPG_SOURCE_UNSET="未指定"
+UPG_SOURCE_ROLLBACK_TAG="(回退)"
diff --git a/scripts/lang/chs/bot_tg.lang b/scripts/lang/chs/bot_tg.lang
new file mode 100644
index 00000000..2153d311
--- /dev/null
+++ b/scripts/lang/chs/bot_tg.lang
@@ -0,0 +1,68 @@
+BOT_TG_PRIVATE_HINT="请先通过 \033[32;4mhttps://t.me/BotFather\033[0m 申请TG机器人并获取其\033[36mAPI TOKEN\033[0m"
+BOT_TG_INPUT_TOKEN="请输入你获取到的API TOKEN"
+BOT_TG_PRIVATE_TOP="请向\033[32m你申请的机器人\033[33m而不是BotFather!\033[0m"
+BOT_TG_PUBLIC_HINT="请向机器人:\033[32;4mhttps://t.me/ShellCrashtg_bot\033[0m"
+BOT_TG_SET_DONE="已完成Telegram日志推送设置!"
+BOT_TG_CHATID_RETRY_PREFIX="第"
+BOT_TG_CHATID_RETRY_SUFFIX="次尝试获取对话ID失败,正在重试..."
+BOT_TG_SEND_KEY="发送此秘钥:"
+BOT_TG_SENT_CONFIRM="我已经发送完成"
+BOT_TG_CHATID_FAIL="无法获取对话ID,请返回重新设置或手动输入ChatID!"
+BOT_TG_CHATID_MANUAL_HINT="通常访问"
+BOT_TG_CHATID_MANUAL_HINT2="即可看到ChatID"
+BOT_TG_INPUT_CHATID="请手动输入ChatID"
+BOT_TG_CHATID_RECONFIG="无法获取对话ID,请重新配置!"
+BOT_TG_CRON_NAME="TG_BOT守护进程"
+
+BOT_TG_HELP_GROUP="进群讨论:"
+BOT_TG_HELP_PROJECT="项目地址:"
+BOT_TG_HELP_GUIDE="相关教程:"
+BOT_TG_HELP_COFFEE="请喝咖啡:"
+BOT_TG_HELP_AIRPORT="友情机场:"
+BOT_TG_RUN_ON="🟢正在运行"
+BOT_TG_RUN_OFF="🟡未运行"
+BOT_TG_WELCOME="欢迎使用ShellCrash!"
+BOT_TG_SERVICE="服务"
+BOT_TG_MEM_USED="内存占用:"
+BOT_TG_RUNNING_TIME="已运行:"
+BOT_TG_SELECT_ACTION="请选择操作:"
+BOT_TG_SELECT_FILE="请选择需要上传或下载的具体文件:"
+BOT_TG_BTN_START="✈️ 启用劫持"
+BOT_TG_BTN_PURE="💧 纯净模式"
+BOT_TG_BTN_RESTART="🕹 重启服务"
+BOT_TG_BTN_LOG="📄 查看日志"
+BOT_TG_BTN_TRANSFER="🔃 文件传输"
+BOT_TG_BTN_GET_LOG="📥 下载日志"
+BOT_TG_BTN_GET_BAK="💾 备份设置"
+BOT_TG_BTN_GET_CFG="⬇️ 下载配置"
+BOT_TG_BTN_UP_CORE="🪐 上传内核"
+BOT_TG_BTN_UP_BAK="🔄 还原设置"
+BOT_TG_BTN_UP_CFG="⬆️ 上传配置"
+BOT_TG_NO_CURL="⚠️ 因当前设备缺少curl应用,仅支持上传功能!"
+BOT_TG_UPLOAD_OK="成功!即将重启服务!"
+BOT_TG_UPLOAD_FAIL="失败,请仔细检查文件或重试!"
+BOT_TG_CORE_UPDATE="内核更新"
+BOT_TG_CFG_RESTORED="配置文件已还原,请手动重启服务!"
+BOT_TG_RESTORE_FAIL="解压还原失败,请仔细检查文件或重试!"
+BOT_TG_CFG_UPLOADED="配置文件已上传,请手动重启服务!"
+BOT_TG_UPLOAD_FAIL2="上传失败,请仔细检查文件或重试!"
+BOT_TG_NET_UPLOAD_FAIL="网络错误,上传失败!请重试!"
+BOT_TG_FILE_FORMAT_FAIL="文件格式不匹配,上传失败!"
+BOT_TG_FW_ENABLED="ShellCrash 透明路由"
+BOT_TG_FW_ENABLED_SUFFIX="已启用!"
+BOT_TG_SWITCH_PURE="已切换到纯净模式!"
+BOT_TG_SERVICE_RESTARTED="ShellCrash 服务已重启!"
+BOT_TG_UNFINISHED="错误,还未完成的功能!"
+BOT_TG_SEND_CORE="请发送需要上传的内核,必须是以tar.gz,.gz或.upx结尾的【"
+BOT_TG_SEND_CORE_SUFFIX="】内核!"
+BOT_TG_SEND_BAK="请发送需要还原的备份文件,必须是【.tar.gz】格式!"
+BOT_TG_SEND_CFG="请发送需要上传的配置文件,必须是【"
+BOT_TG_SEND_CFG_SUFFIX="】格式,支持自定义配置文件"
+BOT_TG_SWITCH_TO="已切换到"
+BOT_TG_ALREADY="当前已经是"
+BOT_TG_ALREADY_PURE="当前已经是纯净模式!"
+BOT_TG_SERVICE_RESTARTED_SHORT="🔄 服务已重启"
+BOT_TG_LOG_CONTENT="📄 日志内容如下(已过滤任务日志):"
+BOT_TG_TASK_WORD="任务"
+BOT_TG_INPUT_SUB="✏ 请输入新的订阅链接:"
+BOT_TG_SUB_UPDATED="订阅更新完成:"
diff --git a/scripts/lang/chs/check_port.lang b/scripts/lang/chs/check_port.lang
new file mode 100644
index 00000000..f3dd377e
--- /dev/null
+++ b/scripts/lang/chs/check_port.lang
@@ -0,0 +1,3 @@
+CHECK_PORT_RANGE_ERR="输入错误!请输入正确的数值(1-65535)!"
+CHECK_PORT_DUP_ERR="输入错误!请不要输入重复的端口!"
+CHECK_PORT_OCCUPIED_ERR="当前端口已被其他进程占用,请重新输入!"
diff --git a/scripts/lang/chs/common.lang b/scripts/lang/chs/common.lang
new file mode 100644
index 00000000..6d10dd61
--- /dev/null
+++ b/scripts/lang/chs/common.lang
@@ -0,0 +1,13 @@
+
+COMMON_INPUT="请输入对应数字"
+COMMON_INPUT_L="请输入对应字母或数字"
+COMMON_INPUT_R="是否启用?(1/0) > "
+COMMON_BACK="返回上级菜单"
+COMMON_SUCCESS="操作成功!"
+COMMON_FAILED="操作失败!"
+COMMON_UNSET="未设置"
+COMMON_MOD="模式"
+COMMON_ERR_NUM="请输入正确的数字!"
+COMMON_ERR_LETTER="请输入正确的字母或数字!"
+COMMON_ERR_INPUT="输入错误,请重新输入!"
+COMMON_ERR_CANCEL="操作已取消!"
diff --git a/scripts/lang/chs/ddns.lang b/scripts/lang/chs/ddns.lang
new file mode 100644
index 00000000..1240b036
--- /dev/null
+++ b/scripts/lang/chs/ddns.lang
@@ -0,0 +1,35 @@
+DDNS_WELCOME="欢迎使用DDNS!"
+DDNS_ADD_DONE="服务已经添加!"
+DDNS_INPUT_DOMAIN="请输入你的域名"
+DDNS_INPUT_USER="请输入用户名或邮箱"
+DDNS_INPUT_PASS="请输入密码或令牌秘钥"
+DDNS_INPUT_CHECK_INTERVAL="请输入检测更新间隔(单位:分钟;默认为10)"
+DDNS_INPUT_FORCE_INTERVAL="请输入强制更新间隔(单位:小时;默认为24)"
+DDNS_CONFIRM_INFO="请核对如下信息:"
+DDNS_FIELD_SERVICE="服务商:"
+DDNS_FIELD_DOMAIN="域名:"
+DDNS_FIELD_USER="用户名:"
+DDNS_FIELD_INTERVAL="检测间隔:"
+DDNS_CONFIRM_ADD="是否确认添加:"
+DDNS_YES="是"
+DDNS_REINPUT="否,重新輸入"
+DDNS_LIST_NOT_FOUND="未找到DDNS列表文件,尝试在线获取……"
+DDNS_DOWNLOAD_FAILED="下载失败,请重试!"
+DDNS_SELECT_PROVIDER="请选择服务提供商:"
+DDNS_INPUT_ERROR="输入错误,请重新输入!"
+DDNS_SELECT_NETMODE="请选择网络模式:"
+DDNS_IPV4="IPV4"
+DDNS_IPV6="IPV6"
+DDNS_DISABLE="停用"
+DDNS_ENABLE="启用"
+DDNS_UPDATE_NOW="立即更新"
+DDNS_EDIT_CURRENT="编辑当前服务"
+DDNS_CURRENT_SERVICE="当前服务"
+DDNS_REMOVE_CURRENT="移除当前服务"
+DDNS_VIEW_LOG="查看运行日志"
+DDNS_NOT_SUPPORTED="本脚本依赖OpenWrt内置的DDNS服务,当前设备无法运行,已退出!"
+DDNS_LIST_HEADER=" 列表 域名 启用 IP地址"
+DDNS_ADD_SERVICE="添加DDNS服务"
+DDNS_EXIT="退出"
+DDNS_INPUT_INDEX="请输入对应序号"
+DDNS_INPUT_NUM_ERROR="请输入正确数字!"
diff --git a/scripts/lang/chs/dns.lang b/scripts/lang/chs/dns.lang
new file mode 100644
index 00000000..2ab7aa99
--- /dev/null
+++ b/scripts/lang/chs/dns.lang
@@ -0,0 +1,67 @@
+#=====DNS主菜单=====
+DNS_CURRENT_MODE="当前DNS运行模式为:"
+DNS_RESTART_NOTICE="切换模式后需要手动重启服务以生效!"
+
+DNS_MODE_MIX_DESC="CN域名DIRECT-DNS,其它fake-ip"
+DNS_MODE_ROUTE_DESC="CN域名DIRECT-DNS,其它PROXY-DNS"
+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_RESOLVER="修改DEFAULT-DNS(必须是IP,用于解析其他DNS)"
+DNS_ADV_EDIT_PROXY_SERVER="修改PROXY-SERVER-DNS(必须是IP,用于解析节点域名)"
+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内核"
+DNS_SET_TO="设为"
+DNS_REMOVE_OK="移除成功"
+DNS_REMOVE_FAIL="移除失败"
+DNS_INPUT_REDIR_PORT="请输入第三方应用的DNS监听端口"
+DNS_INPUT_REDIR_RESET="或输入 r 重置DNS劫持端口"
+DNS_INPUT_REDIR_BACK="或输入 0 返回上级菜单"
+DNS_INPUT="请输入"
+DNS_CONFIRM_ADD="请确认需要添加的地址:"
+DNS_CONFIRM_OK="确认无误"
+DNS_ADD_OK="添加成功"
+DNS_ADD_FAIL="添加失败"
+DNS_NOW="当前DNS:"
+DNS_INPUT_NEW="请直接输入新的DNS地址"
+DNS_INPUT_RESET="或输入 r 重置DNS地址"
diff --git a/scripts/lang/chs/fw_filter.lang b/scripts/lang/chs/fw_filter.lang
new file mode 100644
index 00000000..6f315a41
--- /dev/null
+++ b/scripts/lang/chs/fw_filter.lang
@@ -0,0 +1,91 @@
+FWF_TITLE="流量过滤"
+FWF_ITEM_1_PREFIX="1) 过滤非常用端口:\t"
+FWF_ITEM_1_SUFFIX="—用于过滤P2P流量"
+FWF_ITEM_2_PREFIX="2) 过滤局域网设备:\t"
+FWF_ITEM_2_SUFFIX="—使用黑/白名单进行过滤"
+FWF_ITEM_3_PREFIX="3) 过滤QUIC协议:\t"
+FWF_ITEM_3_SUFFIX="—优化视频性能"
+FWF_ITEM_4_PREFIX="4) 过滤CN_IP(4&6)列表:"
+FWF_ITEM_4_SUFFIX="—优化性能"
+FWF_ITEM_5="5) 自定义透明路由ipv4网段:适合vlan等复杂网络环境"
+FWF_ITEM_6="6) 自定义保留地址ipv4网段:需要以保留地址为访问目标的环境"
+FWF_BACK="0) $COMMON_BACK"
+FWF_SWITCH_STOP="切换时将停止服务,是否继续:"
+FWF_YES="1) 是"
+FWF_NO_BACK="0) 否,返回上级菜单"
+FWF_QUIC_OFF="已禁止QUIC流量通过ShellCrash内核!"
+FWF_QUIC_ON="已取消禁止QUIC协议流量!"
+FWF_CNIP_ON="已开启CN_IP绕过内核功能!"
+FWF_CNIP_WARN="注意:此功能会导致全局模式及一切CN相关规则失效!"
+FWF_CNIP_OFF="已禁用CN_IP绕过内核功能!"
+FWF_NO_IPSET="当前设备缺少ipset模块或未使用nftables模式,无法启用绕过功能!"
+FWF_WHITE_LIST="白名单"
+FWF_BLACK_LIST="黑名单"
+FWF_PASS_WORD="不"
+FWF_COMMON_NOTE="注意:\n"
+FWF_MIX_NOTE="MIX模式下,所有fake-ip来源的非常用端口流量不会被过滤"
+FWF_ALLOWED_PORTS="当前已放行端口:"
+FWF_PORT_MENU_1_PREFIX="1) 启用/关闭端口过滤: \t"
+FWF_PORT_MENU_1_SUFFIX=""
+FWF_PORT_MENU_2="2) 添加放行端口"
+FWF_PORT_MENU_3="3) 移除指定放行端口"
+FWF_PORT_MENU_4="4) 重置默认放行端口"
+FWF_PORT_MENU_5="5) 重置为旧版放行端口"
+FWF_MAX_PORT="最多支持设置放行15个端口,请先减少一些!"
+FWF_INPUT_ADD_HINT="请直接输入要放行的端口号"
+FWF_INPUT_ADD_HINT2="(每次只能输入一个端口号,切勿一次添加多个端口号)"
+FWF_INPUT_REMOVE_HINT="请直接输入要移除的端口号"
+FWF_OR_BACK="或输入 0 返回上级菜单"
+FWF_ERR_DUP="输入错误!请勿重复添加!"
+FWF_ERR_RANGE="输入错误!请输入正确的数值(1~65535)!"
+FWF_INPUT_PORT="请输入> "
+FWF_CUST_HOST_TITLE="当前默认透明路由的网段为:"
+FWF_CUST_HOST_TITLE2="当前已添加的自定义网段为:"
+FWF_CUST_HOST_MENU_1="1) 移除所有自定义网段"
+FWF_CUST_HOST_MENU_2="2) 使用自定义网段覆盖默认网段"
+FWF_CUST_HOST_HINT="请输入对应的序号或需要额外添加的网段> "
+FWF_NET_ERR="请输入正确的网段地址!"
+FWF_RESERVE_NOTE="注意:地址必须是空格分隔,错误的设置可能导致网络回环或启动报错,请务必谨慎!"
+FWF_RESERVE_NOW="当前网段:"
+FWF_RESERVE_INPUT_HINT="请直接输入自定义保留地址ipv4网段"
+FWF_RESERVE_INPUT_HINT2="或输入 1 重置默认网段"
+FWF_RESERVE_INPUT_HINT3="或输入 0 返回上级菜单"
+FWF_RESERVE_PROMPT="请输入> "
+FWF_RESERVE_SET="已将保留地址网段设为:"
+FWF_RESERVE_ERR="输入有误,请重新输入!"
+FWF_LAN_NO_DEVICE="未知设备"
+FWF_MAC_HINT="手动输入mac地址时仅支持\033[32mxx:xx:xx:xx:xx:xx\033[0m的形式"
+FWF_MAC_EXISTED="已添加的mac地址:"
+FWF_NONE_MAC="暫未添加任何mac地址"
+FWF_MAC_HEADER="序号 \033[33m设备IP 设备mac地址 设备名称\033[0m"
+FWF_MAC_NONE="无纪录"
+FWF_MAC_INPUT_HINT="请输入对应序号或直接输入mac地址> "
+FWF_MAC_DUP="已添加的设备,请勿重复添加!"
+FWF_IP_HINT="手动输入时仅支持 \033[32m192.168.1.0/24\033[0m 或 \033[32m192.168.1.0\033[0m 的形式"
+FWF_IP_HINT2="不支持ipv6地址过滤,可能导致过滤失败,建议使用mac地址过滤"
+FWF_IP_EXISTED="已添加的IP地址(段):"
+FWF_NONE_IP="暫未添加任何IP地址(段)"
+FWF_IP_HEADER="\033[33m序号 设备IP 设备名称\033[32m"
+FWF_IP_INPUT_HINT="请输入对应序号或直接输入IP地址段> "
+FWF_IP_DUP="已添加的地址,请勿重复添加!"
+FWF_REMOVE_NONE="列表中没有需要移除的设备!"
+FWF_REMOVE_TITLE="请选择需要移除的设备:"
+FWF_REMOVE_HEADER=" \033[32m设备IP \033[36m设备mac地址 \033[35m设备名称\033[0m"
+FWF_REMOVE_OK="对应设备已移除!"
+FWF_FILTER_MENU_TITLE="请在此添加或移除设备"
+FWF_FILTER_MODE="当前过滤方式为:"
+FWF_FILTER_ONLY="仅列表内设备流量"
+FWF_FILTER_MODE_SUFFIX="模式"
+FWF_FILTER_PASS="经过"
+FWF_FILTER_BLACK_DESC="仅列表内设备流量不经过内核"
+FWF_FILTER_WHITE_DESC="仅列表内设备流量经过内核"
+FWF_FILTER_EXISTED="当前已过滤设备为:"
+FWF_FILTER_HEADER=" \033[36m设备mac/ip地址\033[0m \033[35m设备名称\033[0m"
+FWF_FILTER_SWITCH_PREFIX="1) 切换为"
+FWF_FILTER_SWITCH_SUFFIX="模式"
+FWF_FILTER_ADD_MAC="2) \033[32m添加指定设备(mac地址)\033[0m"
+FWF_FILTER_ADD_IP="3) \033[32m添加指定设备(IP地址/网段)\033[0m"
+FWF_FILTER_REMOVE="4) \033[36m移除指定设备\033[0m"
+FWF_FILTER_CLEAR="9) \033[31m清空整个列表\033[0m"
+FWF_SWITCH_OK="已切换成功!"
+FWF_LIST_CLEARED="设备列表已清空!"
diff --git a/scripts/lang/chs/menu.lang b/scripts/lang/chs/menu.lang
new file mode 100644
index 00000000..9615b9cb
--- /dev/null
+++ b/scripts/lang/chs/menu.lang
@@ -0,0 +1,89 @@
+# ===== 通用提示 =====
+
+MENU_RESTART_NOTICE="检测到配置变更,是否立即重启服务以应用新配置?"
+MENU_RESTART_NOW="立即重启"
+MENU_RESTART_LATER="暂不重启"
+
+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_YES="是"
+MENU_NO="否"
+
+# ===== 欢迎与状态 =====
+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_LOAD_NOW="立即加载"
+MENU_LOAD_LATER="暂不加载"
+
+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="发布页面:"
diff --git a/scripts/lang/chs/override.lang b/scripts/lang/chs/override.lang
new file mode 100644
index 00000000..a5a0171e
--- /dev/null
+++ b/scripts/lang/chs/override.lang
@@ -0,0 +1,93 @@
+OVR_TITLE="配置文件覆写"
+OVR_MENU_2="2) 管理\033[36m自定义规则\033[0m"
+OVR_MENU_3="3) 管理\033[33m自定义节点\033[0m"
+OVR_MENU_4="4) 管理\033[36m自定义策略组\033[0m"
+OVR_MENU_5="5) \033[32m自定义\033[0m高级功能"
+OVR_MENU_9="9) \033[33m禁用\033[0m配置文件覆写"
+OVR_BACK="0) 返回上级菜单"
+OVR_INPUT_NUM="请输入对应数字> "
+OVR_PROMPT="请输入> "
+OVR_GROUPS_CHOOSE_TYPE="请选择策略组的类型:"
+OVR_GROUP_TYPE_CN="手动选择 自动选择 故障转移 负载均衡"
+OVR_WARN_1="此功能可能会导致严重问题!启用后脚本中大部分功能都将禁用!!!"
+OVR_WARN_2_PREFIX="如果你不是非常了解"
+OVR_WARN_2_SUFFIX="的运行机制,切勿开启!"
+OVR_WARN_3="继续后如出现任何问题,请务必自行解决,一切提问恕不受理!"
+OVR_WARN_CONFIRM="1) 我确认遇到问题可以自行解决"
+OVR_CONFIRM_YES="1) 是"
+OVR_CONFIRM_NO="0) 否,返回上级菜单"
+OVR_RULES_TITLE="自定义规则"
+OVR_RULES_MENU_HINT="你可以在这里快捷管理自定义规则"
+OVR_RULES_MANUAL="如需批量操作,请手动编辑:\033[36m $YAMLSDIR/rules.yaml\033[0m"
+OVR_RULES_SHARED="singbox和clash共用此处规则,可无缝切换!"
+OVR_RULES_WARN="大量规则请尽量使用rule-set功能添加,\n\033[31m此处过量添加可能导致启动卡顿!\033[0m"
+OVR_RULES_ADD="1) 新增自定义规则"
+OVR_RULES_DEL="2) 移除自定义规则"
+OVR_RULES_CLEAR="3) 清空规则列表"
+OVR_RULES_BYPASS="4) 配置节点绕过:"
+OVR_RULES_NO_RULES="请先添加自定义规则!"
+OVR_RULES_CLEAR_CONFIRM="是否确认清空全部自定义规则?"
+OVR_RULES_ADD_RULE="请输入规则语句,\n可以是域名、泛域名、IP网段或者其他匹配规则类型的内容"
+OVR_RULES_TYPE="请选择规则类型:"
+OVR_RULES_GROUP="请选择具体规则"
+OVR_RULES_EXIST_WARN="此处规则读取自现有配置文件,如果你后续更换配置文件时运行出错,请尝试重新添加"
+OVR_RULES_INPUT_RULE="请输入对应规则> "
+OVR_RULES_INPUT_NUM="请输入对应数字> "
+OVR_RULES_INPUT_TYPE="请输入对应数字> "
+OVR_RULES_INPUT_SELECT="请输入对应数字> "
+OVR_RULES_DEL_HINT="输入对应数字即可移除相应规则:"
+OVR_RULES_ADD_OK="添加成功!"
+OVR_RULES_BYPASS_WARN1="本功能会自动将当前配置文件中的节点域名或IP设置为直连规则以防止出现双重流量!"
+OVR_RULES_BYPASS_WARN2="请确保下游设备使用的节点与ShellCrash中使用的节点相同,否则无法生效!"
+OVR_RULES_BYPASS_PROMPT="是否启用节点绕过?"
+OVR_RULES_BYPASS_CONFIRM="是否确认清空全部自定义规则?"
+OVR_GROUPS_TITLE="自定义clash策略组"
+OVR_GROUPS_MENU_HINT="你可以在这里快捷管理自定义策略组"
+OVR_GROUPS_MANUAL="如需修改或批量操作,请手动编辑:$YAMLSDIR/proxy-groups.yaml"
+OVR_GROUPS_ADD="1) 添加自定义策略组"
+OVR_GROUPS_VIEW="2) 查看自定义策略组"
+OVR_GROUPS_CLEAR="3) 清空自定义策略组"
+OVR_GROUPS_WARN1="注意策略组名称必须和【自定义规则】或【自定义节点】功能中指定的策略组一致!"
+OVR_GROUPS_WARN2="建议先创建策略组,之后可在【自定义规则】或【自定义节点】功能中智能指定"
+OVR_GROUPS_WARN3="如需在当前策略组下添加节点,请手动编辑$YAMLSDIR/proxy-groups.yaml"
+OVR_GROUPS_INPUT_NAME="请直接输入自定义策略组名称\n(不支持纯数字且不要包含特殊字符!)"
+OVR_GROUPS_INPUT_NUM="请输入对应数字> "
+OVR_GROUPS_URL="请输入测速地址"
+OVR_GROUPS_URL_HINT="或直接回车使用默认地址:https://www.gstatic.com/generate_204"
+OVR_GROUPS_MULTI_HINT="如需添加到多个策略组,请一次性输入多个数字并用空格隔开"
+OVR_GROUPS_SKIP="0) 跳过添加"
+OVR_GROUPS_CLEAR_CONFIRM="是否确认清空全部自定义策略组?"
+OVR_GROUPS_ADD_OK="添加成功!"
+OVR_PROXIES_TITLE="自定义clash节点"
+OVR_PROXIES_MENU_HINT="你可以在这里快捷管理自定义节点"
+OVR_PROXIES_MANUAL="如需批量操作,请手动编辑:$YAMLSDIR/proxies.yaml"
+OVR_PROXIES_ADD="1) 添加自定义节点"
+OVR_PROXIES_MANAGE="2) 管理自定义节点"
+OVR_PROXIES_CLEAR="3) 清空自定义节点"
+OVR_PROXIES_BYPASS="4) 配置节点绕过:"
+OVR_PROXIES_WARN1="注意\n节点格式必须是单行、不包括括号、“name:”为开头,例如:"
+OVR_PROXIES_WARN2="更多写法请参考:\033[32mhttps://juewuy.github.io/\033[0m"
+OVR_PROXIES_INPUT="请直接输入自定义节点"
+OVR_PROXIES_BLOCK_HASH="绝对禁止包含【#】号!"
+OVR_PROXIES_ADD_HINT="请选择想要将节点添加到的策略组"
+OVR_PROXIES_MULTI_HINT="如需添加到多个策略组,请一次性输入多个数字并用空格隔开"
+OVR_PROXIES_GROUP_HINT="如需自定义策略组,请先使用【管理自定义策略组功能】添加"
+OVR_PROXIES_EXIST_HINT="输入节点对应数字可以移除对应节点"
+OVR_PROXIES_EXIST_TITLE="当前已添加的自定义节点为:"
+OVR_PROXIES_NO_PROXY="请先添加自定义节点!"
+OVR_PROXIES_CLEAR_CONFIRM="是否确认清空全部自定义节点?"
+OVR_PROXIES_BYPASS_WARN1="本功能会自动将当前配置文件中的节点域名或IP设置为直连规则以防止出现双重流量!"
+OVR_PROXIES_BYPASS_WARN2="请确保下游设备使用的节点与ShellCrash中使用的节点相同,否则无法生效!"
+OVR_PROXIES_BYPASS_PROMPT="是否确定启用节点绕过:"
+OVR_PROXIES_ADD_OK="添加成功!"
+OVR_ADV_USER_CREATED1="已经创建自定义设定文件:$YAMLSDIR/user.yaml !"
+OVR_ADV_USER_CREATED2="可用于编写自定义的DNS等功能"
+OVR_ADV_USER_CREATED3="已经创建自定义功能文件:$YAMLSDIR/others.yaml !"
+OVR_ADV_USER_CREATED4="可用于编写自定义的锚点、入站、proxy-providers、rule-set、sub-rules、script等功能"
+OVR_ADV_WIN="Windows下请使用\033[33mWinSCP软件\033[0m进行编辑!"
+OVR_ADV_MAC="MacOS下请使用\033[33mSecureFX软件\033[0m进行编辑!"
+OVR_ADV_LIN="Linux可使用\033[33mvim\033[0m进行编辑(路由设备若不显示中文请勿使用)!"
+OVR_SING_TITLE1="支持覆盖脚本设置的模块有:"
+OVR_SING_TITLE2="支持与内置功能合并(但不可冲突)的模块有:"
+OVR_SING_TITLE3="将相应json文件放入\033[33m$JSONSDIR\033[0m目录后即可在启动时自动加载"
+OVR_SING_TITLE4="使用前请务必参考配置教程:\033[32;4m https://juewuy.github.io/nWTjEpkSK \033[0m"
diff --git a/scripts/lang/chs/providers.lang b/scripts/lang/chs/providers.lang
new file mode 100644
index 00000000..f92e2ce1
--- /dev/null
+++ b/scripts/lang/chs/providers.lang
@@ -0,0 +1,25 @@
+PROVIDERS_MENU_GEN="生成包含全部提供者的配置文件"
+PROVIDERS_MENU_TEMPLATE="选择\033[33m规则模版\033[0m"
+PROVIDERS_MENU_CLEAN="\033[33m清理\033[0mproviders目录文件"
+PROVIDERS_INPUT="请输入对应字母或数字"
+
+PROVIDERS_EMPTY_HINT="你还未添加链接或本地配置文件,请先添加!"
+PROVIDERS_TEMPLATE_CURRENT="当前规则模版为:"
+PROVIDERS_TEMPLATE_SELECT="请选择在线模版:"
+PROVIDERS_TEMPLATE_LOCAL="使用\033[36m本地模版\033[0m"
+PROVIDERS_TEMPLATE_PATH="请输入模版的路径(绝对路径)"
+PROVIDERS_TEMPLATE_NOT_FOUND="输入错误,找不到对应模版文件!"
+
+PROVIDERS_CLEAN_WARN="将清空"
+PROVIDERS_CLEAN_WARN_END="目录下所有内容"
+PROVIDERS_CLEAN_CONFIRM="是否继续?"
+
+PROVIDERS_FETCHING_TEMPLATE="正在获取在线模版......"
+PROVIDERS_DOWNLOAD_FAILED="下载失败,请尝试更换安装源!"
+PROVIDERS_GEN_OK="配置文件生成成功!"
+PROVIDERS_GEN_OK_SINGBOX="配置文件生成成功!如果启动超时建议更新里手动安装Singbox-srs数据库常用包!"
+PROVIDERS_GEN_FAILED="生成配置文件出错,请仔细检查输入!"
+PROVIDERS_RESTART_ASK="是否立即启动/重启服务?"
+PROVIDERS_YES="是"
+PROVIDERS_NO="否"
+PROVIDERS_CRON_SUB_UPDATE="更新订阅"
diff --git a/scripts/lang/chs/set_crashdir.lang b/scripts/lang/chs/set_crashdir.lang
new file mode 100644
index 00000000..0ba99bbe
--- /dev/null
+++ b/scripts/lang/chs/set_crashdir.lang
@@ -0,0 +1,34 @@
+SCD_SELECT_INSTALL_DIR="请选择安装目录:"
+SCD_INPUT_NUM="请输入相应数字"
+SCD_INPUT_ERROR="输入错误!请重新设置!"
+SCD_XIAOMI_DETECTED="检测到当前设备为小米官方系统,请选择安装位置:"
+SCD_CUSTOM_DIR_WARN="自定义目录(不推荐,不明勿用!)"
+SCD_EXIT_INSTALL="退出安装"
+SCD_SELECT_USB_DIR="请选择U盘目录:"
+SCD_ASUS_DM_NOT_FOUND="未找到下载大师自启文件:"
+SCD_CHECK_SETTING="请检查设置!"
+SCD_ASUS_DETECTED="检测到当前设备为华硕固件,请选择安装方式"
+SCD_ASUS_INSTALL_DM="基于U盘+下载大师安装(支持所有固件,限ARM设备,须插入U盘或移动硬盘)"
+SCD_ASUS_INSTALL_SCRIPT="基于自启脚本安装(仅持部分梅林固件)"
+SCD_ASUS_DM_HINT="请先在路由器网页后台安装下载大师并启用,之后选择外置存储所在目录!"
+SCD_ASUS_REINSTALL_HINT="如开机无法正常自启,请重新使用U盘+下载大师安装!"
+SCD_PATH_FORMAT_HINT="路径是必须带 / 的格式,注意写入虚拟内存(/tmp,/opt,/sys...)的文件会在重启后消失!"
+SCD_PATH_FREE_SPACE="可用路径 剩余空间:"
+SCD_INPUT_CUSTOM_DIR="请输入自定义路径"
+SCD_PATH_ERROR="路径错误!请重新设置!"
+SCD_INSTALL_SPACE_HINT="注意:安装ShellCrash至少需要预留约1MB的磁盘空间"
+SCD_INSTALL_ETC="在\033[32m/etc目录\033[0m下安装(适合root用户)"
+SCD_INSTALL_USR="在\033[32m/usr/share目录\033[0m下安装(适合Linux系统)"
+SCD_INSTALL_HOME="在\033[32m当前用户目录\033[0m下安装(适合非root用户)"
+SCD_INSTALL_USB="在\033[32m外置存储\033[0m中安装"
+SCD_INSTALL_MANUAL="手动设置安装目录"
+SCD_INSTALL_CANCELED="安装已取消"
+SCD_NO_WRITE_PREFIX="没有"
+SCD_NO_WRITE_SUFFIX="目录写入权限!请重新设置!"
+SCD_TARGET_DIR_PREFIX="目标目录"
+SCD_TARGET_DIR_SPACE="空间剩余:"
+SCD_CONFIRM_INSTALL="是否确认安装?"
+SCD_YES="是"
+SCD_NO="否"
+SCD_DIR_FREE="目录,剩余空间:"
+SCD_SOFT_SOLID="(支持软固化功能)"
diff --git a/scripts/lang/chs/setboot.lang b/scripts/lang/chs/setboot.lang
new file mode 100644
index 00000000..58c5034c
--- /dev/null
+++ b/scripts/lang/chs/setboot.lang
@@ -0,0 +1,52 @@
+SETBOOT_NOT_SET="未设置"
+SETBOOT_SECOND="秒"
+SETBOOT_TITLE="启动设置菜单"
+SETBOOT_ITEM_AUTO="开机自启动:"
+SETBOOT_ITEM_OLD="使用保守模式:"
+SETBOOT_ITEM_OLD_DESC="———基于定时任务(每分钟检测)"
+SETBOOT_ITEM_DELAY="设置自启延时:"
+SETBOOT_ITEM_DELAY_DESC="———用于解决自启后服务受限"
+SETBOOT_ITEM_MINI="启用小闪存模式:"
+SETBOOT_ITEM_MINI_DESC="———用于闪存空间不足的设备"
+SETBOOT_ITEM_MINI_DIR="设置小闪存目录:"
+SETBOOT_ITEM_NETCHK="自启网络检查:"
+SETBOOT_ITEM_NETCHK_DESC="———禁用则跳过自启时网络检查"
+SETBOOT_VIEW_LOG="查看启动日志"
+SETBOOT_AUTO_OFF="已禁止ShellCrash开机自启动!"
+SETBOOT_AUTO_ON="已设置ShellCrash开机自启动!"
+SETBOOT_CRON_INIT="ShellCrash初始化"
+SETBOOT_OLDMODE_ON="改为使用保守模式启动服务!"
+SETBOOT_OLDMODE_OFF="改为使用系统守护进程启动服务!"
+SETBOOT_MODE_UNSUPPORTED="当前设备不支持以其他模式启动!"
+SETBOOT_DELAY_HINT1="如果你的设备启动后可以正常使用,则无需设置!"
+SETBOOT_DELAY_HINT2="推荐设置为30~120秒之间,请根据设备问题自行试验"
+SETBOOT_DELAY_INPUT="请输入启动延迟时间(0~300秒)"
+SETBOOT_SET_OK="设置成功!"
+SETBOOT_DELAY_INVALID="输入有误,或超过300秒,请重新输入!"
+SETBOOT_MINI_NEEDED_NO="您的设备空间充足(>20M),无需开启!"
+SETBOOT_SYSTEMD_WARN="不支持systemd启动模式,请先启用保守模式!"
+SETBOOT_MINI_ENABLED="已经启用小闪存功能!"
+SETBOOT_MINI_DIR_HINT="如需更换目录,请使用【设置小闪存目录】功能"
+SETBOOT_MINI_DISABLE_WARN="您的设备剩余空间不足8M,停用后可能无法正常运行!"
+SETBOOT_MINI_DISABLE_CONFIRM="是否确认停用此功能?"
+SETBOOT_YES="是"
+SETBOOT_NO_BACK="否,返回上级菜单"
+SETBOOT_MINI_DISABLED="已经停用小闪存功能!"
+SETBOOT_BINDIR_HINT1="如设置到内存,则每次开机后都自动重新下载相关文件"
+SETBOOT_BINDIR_HINT2="请确保安装源可用裸连,否则会导致启动失败"
+SETBOOT_BINDIR_TMP="使用内存(/tmp)"
+SETBOOT_BINDIR_USB="选择U盘目录"
+SETBOOT_BINDIR_CUSTOM="自定义目录"
+SETBOOT_SELECT_INSTALL_DIR="请选择安装目录:"
+SETBOOT_SPACE_USED="已占用的储存空间:"
+SETBOOT_INPUT_ERROR="输入错误!请重新设置!"
+SETBOOT_INPUT_CMD="请直接输入命令语句"
+SETBOOT_INPUT_OR_BACK="或输入 0 返回上级菜单"
+SETBOOT_INPUT="请输入"
+SETBOOT_NETCHK_HINT1="如果你的设备启动后可以正常使用,则无需变更设置!"
+SETBOOT_NETCHK_HINT2="禁用时,如果使用了小闪存模式或者rule-set等在线规则,则可能会因无法联网而导致启动失败!"
+SETBOOT_NETCHK_HINT3="启用时,会导致部分性能较差或者拨号较慢的设备可能会因查询超时导致启动失败!"
+SETBOOT_NETCHK_OFF_CONFIRM="当前\033[33m已禁用\033[0m自启网络检查,是否确认启用?"
+SETBOOT_NETCHK_ON_CONFIRM="当前\033[33m已启用\033[0m自启网络检查,是否确认禁用?"
+SETBOOT_TASK_WORD="任务"
+SETBOOT_LOG_NOT_FOUND="未找到相关日志!"
diff --git a/scripts/lang/chs/subconverter.lang b/scripts/lang/chs/subconverter.lang
new file mode 100644
index 00000000..1b99a0ec
--- /dev/null
+++ b/scripts/lang/chs/subconverter.lang
@@ -0,0 +1,33 @@
+SUBCONVERTER_MENU_GEN="生成包含全部节点、订阅的配置文件"
+SUBCONVERTER_MENU_EXCLUDE="设置\033[31m排除节点正则\033[0m"
+SUBCONVERTER_MENU_INCLUDE="设置\033[32m包含节点正则\033[0m"
+SUBCONVERTER_MENU_RULE="选择\033[33m在线规则模版\033[0m"
+SUBCONVERTER_MENU_SERVER="选择Subconverter服务器"
+SUBCONVERTER_MENU_UA="自定义浏览器UA"
+
+SUBCONVERTER_INPUT="请输入"
+SUBCONVERTER_BACK="或输入 0 返回上级菜单"
+
+SUBCONVERTER_EXCLUDE_HINT1="匹配关键字的节点会在导入时被【屏蔽】!"
+SUBCONVERTER_INCLUDE_HINT1="仅有匹配关键字的节点才会被【导入】!!!"
+SUBCONVERTER_KEYWORD_SPLIT="多个关键字可以用\033[30;47m | \033[0m号分隔"
+SUBCONVERTER_REGEX_HINT="\033[32m支持正则表达式\033[0m,空格请使用\033[30;47m + \033[0m号替代"
+SUBCONVERTER_EXCLUDE_INPUT="请直接输入节点过滤关键字"
+SUBCONVERTER_INCLUDE_INPUT="请直接输入节点匹配关键字"
+SUBCONVERTER_EXCLUDE_CLEAR="或输入 d \033[31m清空\033[0m节点过滤关键字"
+SUBCONVERTER_INCLUDE_CLEAR="或输入 d \033[31m清空\033[0m节点匹配关键字"
+
+SUBCONVERTER_RULE_CURRENT="当前使用规则为:"
+SUBCONVERTER_SERVER_HINT="以下为互联网采集的第三方服务器,具体安全性请自行斟酌!"
+SUBCONVERTER_SERVER_THANKS="感谢以下作者的无私奉献!!!"
+SUBCONVERTER_SERVER_CURRENT="当前使用后端为:"
+SUBCONVERTER_SET_OK="设置成功!返回上级菜单"
+
+SUBCONVERTER_UA_HINT="无法正确获取配置文件时可尝试使用"
+SUBCONVERTER_UA_CURRENT="当前UA:"
+SUBCONVERTER_UA_AUTO="使用自动UA(默认)"
+SUBCONVERTER_UA_NONE="不使用UA"
+SUBCONVERTER_UA_CUSTOM="使用自定义UA"
+SUBCONVERTER_UA_CLEAR="清空UA"
+SUBCONVERTER_UA_CUSTOM_WARN="注意:\n自定义UA不可包含空格或特殊符号!"
+SUBCONVERTER_UA_CUSTOM_INPUT="请直接输入自定义UA"
diff --git a/scripts/lang/chs/task_cmd.lang b/scripts/lang/chs/task_cmd.lang
new file mode 100644
index 00000000..a4148521
--- /dev/null
+++ b/scripts/lang/chs/task_cmd.lang
@@ -0,0 +1,19 @@
+TASK_CMD_EVERY="每隔"
+TASK_CMD_HOURLY="时每"
+TASK_CMD_MIN="分钟"
+TASK_CMD_CORE_SKIP="任务【自动更新内核】中止-未检测到版本更新"
+TASK_CMD_CORE_DONE="任务【自动更新内核】下载完成,正在重启服务!"
+TASK_CMD_CORE_DL_FAIL="任务【自动更新内核】出错-下载失败!"
+TASK_CMD_CORE_VERIFY_FAIL="任务【自动更新内核】出错-内核校验失败!"
+TASK_CMD_SCRIPT_SKIP="任务【自动更新脚本】中止-未检测到版本更新"
+TASK_CMD_SCRIPT_UNZIP_FAIL="任务【自动更新脚本】出错-解压失败!"
+TASK_CMD_DB_SKIP_PREFIX="任务【自动更新数据库文件】跳过-未检测到"
+TASK_CMD_DB_SKIP_SUFFIX="版本更新"
+TASK_CMD_DB_DL_FAIL_PREFIX="任务【自动更新数据库文件】更新【"
+TASK_CMD_DB_DL_FAIL_SUFFIX="】下载失败!"
+TASK_CMD_DB_OK_PREFIX="任务【自动更新数据库文件】更新【"
+TASK_CMD_DB_OK_SUFFIX="】成功!"
+TASK_CMD_RES_OK="成功"
+TASK_CMD_RES_FAIL="失败"
+TASK_CMD_EXEC_PREFIX="任务【"
+TASK_CMD_EXEC_MID="】执行"
diff --git a/scripts/lang/chs/uninstall.lang b/scripts/lang/chs/uninstall.lang
new file mode 100644
index 00000000..53267d7a
--- /dev/null
+++ b/scripts/lang/chs/uninstall.lang
@@ -0,0 +1,13 @@
+UNINSTALL_WARN="警告:该操作不可逆!"
+UNINSTALL_CONFIRM="是否确认卸载ShellCrash?"
+UNINSTALL_YES="是"
+UNINSTALL_NO="否"
+UNINSTALL_KEEP_CONFIRM="是否保留脚本配置及订阅文件?"
+UNINSTALL_ENV_ERROR="环境变量配置有误,请尝试手动移除安装目录!"
+UNINSTALL_DONE="已卸载ShellCrash相关文件!有缘再会!"
+UNINSTALL_CLOSE_HINT="请手动关闭当前窗口以重置环境变量!"
+UNINSTALL_CANCELED="操作已取消!"
+UNINSTALL_CRON_CLASH="clash服务"
+UNINSTALL_CRON_SUB="订阅链接"
+UNINSTALL_CRON_INIT="ShellCrash初始化"
+UNINSTALL_SSH_MARK="启用外网访问SSH服务"
diff --git a/scripts/lang/chs/userguide.lang b/scripts/lang/chs/userguide.lang
new file mode 100644
index 00000000..4a8d255d
--- /dev/null
+++ b/scripts/lang/chs/userguide.lang
@@ -0,0 +1,17 @@
+# 新手引导
+UG_WELCOME="欢迎使用新手引导!"
+UG_CHOOSE_ENV="请先选择你的使用环境:"
+UG_TIP_CONFIG="(你之后依然可以在设置中更改各种配置)"
+UG_OPTION_1="路由设备配置局域网透明代理"
+UG_OPTION_2="Linux设备仅配置本机代理"
+UG_OPTION_3="还原之前备份的设置"
+UG_RESTORE_OK="脚本设置已还原!请重新启动脚本!"
+UG_IP_FORWARD_WARN="检测到你的设备尚未开启ip转发,局域网设备将无法正常连接网络,是否立即开启?"
+UG_ENABLE_LOW_MEM="检测到你的安装目录空间不足10M,是否开启小闪存模式?"
+UG_IMPORT_CONFIG="这是运行前的最后一步"
+UG_CONFIG_TIP="你必须拥有一份配置文件才能运行服务!"
+UG_CONFIG_RES="是否立即导入配置文件?"
+UG_FINAL_TIP="很好!现在只需要执行启动就可以愉快的使用了!"
+
+UG_IMPORT_NOW="立即导入"
+UG_IMPORT_LATER="暂不导入"
diff --git a/scripts/lang/en/1_start.lang b/scripts/lang/en/1_start.lang
new file mode 100644
index 00000000..f7d09866
--- /dev/null
+++ b/scripts/lang/en/1_start.lang
@@ -0,0 +1,10 @@
+# ===== Startup =====
+START_SERVICE_OK="Service started successfully!"
+START_WEB_HINT="Dashboard:"
+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!"
diff --git a/scripts/lang/en/2_settings.lang b/scripts/lang/en/2_settings.lang
new file mode 100644
index 00000000..07de5c31
--- /dev/null
+++ b/scripts/lang/en/2_settings.lang
@@ -0,0 +1,158 @@
+# =================================================
+# 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_FW_FILTER_DESC="ports, devices, protocols, or lists"
+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)"
+SET_YES="Yes"
+SET_NO_BACK="No, back"
+SET_SKIP_CERT_NOW="Current status: "
+SET_ENABLED="enabled"
+SET_DISABLED="disabled"
+SET_SKIP_CERT_ENABLE_Q=" skip local certificate verification. Enable now?"
+SET_SKIP_CERT_DISABLE_Q=" skip local certificate verification. Disable now?"
+SET_SNIFFER_NOW="Current status: "
+SET_SNIFFER_ENABLE_Q=" domain sniffer. Enable now?"
+SET_SNIFFER_DISABLE_Q=" domain sniffer. Disable now?"
+SET_LANG_ZH="简体中文"
+SET_LANG_EN="English"
+SET_SWITCH_OK="Switched successfully!"
+SET_MODE_SUFFIX="mode"
+SET_SET_TO="Set to "
+SET_BYPASS_TCP="TCP bypass forwarding"
+SET_BYPASS_TU="TCP&UDP bypass forwarding"
+SET_BYPASS_TCP_DESC="forward TCP traffic only to bypass router"
+SET_BYPASS_TU_DESC="forward TCP&UDP traffic to bypass router"
+SET_FW_AREA_CURRENT="Current hijack scope: "
+SET_WARN="Notice:"
+SET_DESC="Description:"
+SET_BYPASS_WARN_1="This feature has risks. Do not use without network knowledge!"
+SET_BYPASS_WARN_2="For UDP proxy, ensure bypass router runs a UDP-capable mode!"
+SET_BYPASS_WARN_3="With systemd startup, core still runs idle. Conservative mode is recommended!"
+SET_BYPASS_DESC_1="This mode does not start core; it only configures firewall forwarding and downstream devices need no extra gateway/DNS setup"
+SET_BYPASS_DESC_2="Supports firewall routing split and device filtering, supports some cron tasks, but not IPv6"
+SET_INPUT_BYPASS_IPV4="Please enter bypass-router IPv4 address"
+SET_TIPS_ENTER_BACK="Tip: press Enter directly to return"
diff --git a/scripts/lang/en/5_task.lang b/scripts/lang/en/5_task.lang
new file mode 100644
index 00000000..556cbff9
--- /dev/null
+++ b/scripts/lang/en/5_task.lang
@@ -0,0 +1,100 @@
+# Recommended task configuration
+TASK_RECOM_TITLE="Enable the following recommended automatic tasks?"
+
+TASK_RECOM_ITEM_1="Save Dashboard select every 10 minutes"
+TASK_RECOM_ITEM_2="Synchronize NTP after service startup"
+TASK_RECOM_ITEM_3="Daily service restart at 03:00"
+TASK5_RUN_TASK=" run task: "
+TASK5_CONFIRM_ADD_CRON="Confirm adding scheduled task?"
+TASK5_YES="Yes"
+TASK5_NO="No"
+TASK5_TASK_PREFIX="Task ["
+TASK5_TASK_ADDED="] \033[32madded!\033[0m"
+TASK5_USER_ADD_HINT1="Command may contain spaces, please ensure it is executable!"
+TASK5_USER_ADD_HINT2="Do not append conditions. Set conditions after adding command."
+TASK5_USER_ADD_HINT3="You can also edit "
+TASK5_USER_ADD_HINT4=" manually to add commands"
+TASK5_INPUT_CMD="Please input command directly"
+TASK5_OR_BACK="Or input 0 to return"
+TASK5_INPUT="Please enter"
+TASK5_CHECK_INPUT="Please check input: "
+TASK5_INPUT_REMARK="Please enter task remark"
+TASK5_CUSTOM_TASK="custom_task_"
+TASK5_CUSTOM_ADDED="Custom task added!"
+TASK5_INPUT_ERROR="Invalid input, please retry!"
+TASK5_USER_DEL_HINT1="Input ID to remove custom task (built-in tasks won't be affected)"
+TASK5_USER_DEL_HINT2="You may also edit "
+TASK5_NO_CUSTOM_TASK="No custom task has been added yet"
+TASK5_SELECT_ADD="Please select task to add:"
+TASK5_SELECT_COND="Select execution condition for task "
+TASK5_SELECT_COND2=":"
+TASK5_COND_1="Scheduled task \033[32mweekly\033[0m"
+TASK5_COND_2="Scheduled task \033[32mdaily\033[0m"
+TASK5_COND_3="Scheduled task \033[32mhourly\033[0m"
+TASK5_COND_4="Scheduled task \033[32mminutely\033[0m"
+TASK5_WARN_LINE1=" --------- \033[31mWARNING\033[0m ---------"
+TASK5_WARN_LINE2=" Do not use advanced triggers unless you know what you are doing!"
+TASK5_WARN_LINE3=" ----------------------------------------"
+TASK5_COND_5="Service \033[33mbefore start\033[0m"
+TASK5_COND_6="Service \033[33mafter start\033[0m"
+TASK5_COND_7="Service \033[33mrun every minute\033[0m"
+TASK5_COND_8="After firewall service \033[33mrestart\033[0m"
+TASK5_WEEK_HINT1="Input 1~7 for day of week (7=Sunday)"
+TASK5_WEEK_HINT2="Input like 1,4,0 for Monday/Thursday/Sunday"
+TASK5_WEEK_HINT3="Input 1~5 for Monday to Friday"
+TASK5_WEEK_INPUT="Run on which weekday"
+TASK5_HOUR_INPUT1="Run at which hour of that day (0~23)"
+TASK5_CRON_WEEK="Weekly "
+TASK5_CRON_WEEK2=" @ "
+TASK5_OCLOCK=":00"
+TASK5_DAY_HINT1="Input 1,7,15 for run at 1/7/15 o'clock"
+TASK5_DAY_HINT2="Input 6~18 for every hour between 6 and 18"
+TASK5_HOUR_INPUT2="Run at which hour daily (0~23)"
+TASK5_MIN_INPUT="Run at which minute (0~59)"
+TASK5_CRON_DAY="Daily "
+TASK5_POINT=":"
+TASK5_MINUTE=""
+TASK5_EVERY_HOUR_INPUT="Run every how many hours (1~23)"
+TASK5_EVERY="Every "
+TASK5_HOUR=" hour(s)"
+TASK5_EVERY_MIN_INPUT="Run every how many minutes (1~59)"
+TASK5_MIN=" minute(s)"
+TASK5_BFSTART="Before service start "
+TASK5_AFSTART="After service start "
+TASK5_RUNNING_HINT1="Input 10 for every 10 mins, 1440 for every 24 hrs"
+TASK5_RUNNING_HINT2="Values >60 mins will be rounded by hour under current timezone"
+TASK5_RUNNING_INPUT="Run every how many minutes (1~1440)"
+TASK5_RUNNING_PREFIX="During runtime every "
+TASK5_AFFW_HINT="This will inject startup code into /etc/init.d/firewall"
+TASK5_CONFIRM_CONTINUE="Continue?"
+TASK5_AFFW_PREFIX="After firewall restart "
+TASK5_GUARD_WORD="guard"
+TASK5_OLD_PREFIX="legacy-"
+TASK5_NONE_TO_MANAGE="No task available to manage!"
+TASK5_ADDED_TASKS="Added tasks:"
+TASK5_CLEAR_OLD="Clear legacy tasks"
+TASK5_CLEAR_ALL="Clear task list"
+TASK5_OLD_CLEARED="Legacy tasks cleared!"
+TASK5_ALL_CLEARED="All tasks cleared!"
+TASK5_OLD_NOT_SUPPORT="Legacy tasks cannot be managed, remove them?"
+TASK5_NO_BACK="No, return"
+TASK5_CURRENT_TASK="Current task: "
+TASK5_EDIT_TASK="\033[33mEdit\033[0m current task"
+TASK5_DEL_TASK="\033[31mDelete\033[0m current task"
+TASK5_RUN_ONCE="\033[32mRun once\033[0m now"
+TASK5_VIEW_RECORD="View \033[33mexecution record\033[0m"
+TASK5_RUN_OK="success!"
+TASK5_RUN_FAIL="failed!"
+TASK5_RECORD_NOT_FOUND="No execution record found!"
+TASK5_USER_FILE_HEADER="#task_id(>200 in order)#task_command#task_desc(no # in cmd or desc)"
+TASK5_MENU_TITLE="Scheduled Tasks"
+TASK5_MENU_1="Add \033[32mautomatic task\033[0m"
+TASK5_MENU_2="Manage \033[33mtask list\033[0m"
+TASK5_MENU_3="View \033[36mtask logs\033[0m"
+TASK5_MENU_4="Configure \033[36mlog push\033[0m"
+TASK5_MENU_5="Add \033[33mcustom task\033[0m"
+TASK5_MENU_6="Delete \033[33mcustom task\033[0m"
+TASK5_MENU_7="Use \033[32mrecommended settings\033[0m"
+TASK5_TASK_GREP="Task ["
+TASK5_LOG_NOT_FOUND="No task-related log found!"
+TASK5_PUSH_HINT="Please configure push channel and switch in log tools"
diff --git a/scripts/lang/en/6_core_config.lang b/scripts/lang/en/6_core_config.lang
new file mode 100644
index 00000000..ddb83ebe
--- /dev/null
+++ b/scripts/lang/en/6_core_config.lang
@@ -0,0 +1,67 @@
+CORECFG_TITLE="Configuration Management"
+CORECFG_HINT_SELECT_PROVIDER="Input a number to manage corresponding provider"
+CORECFG_MENU_A="\033[32mAdd provider\033[0m (subscription/share link/local file)"
+CORECFG_MENU_B="\033[36mGenerate local config\033[0m"
+CORECFG_MENU_C="\033[33mGenerate online config\033[0m"
+CORECFG_MENU_D="\033[31mClear provider list\033[0m"
+CORECFG_MENU_E="\033[36mCustom config file\033[0m"
+CORECFG_CORE_ONLY="Only for Mihomo/singboxr core, please switch core!"
+CORECFG_ADD_PROVIDER_FIRST="Please add provider first!"
+CORECFG_CLEAR_WARN="Warning: this will delete all providers and cannot be undone!"
+CORECFG_CLEAR_CONFIRM="Confirm clearing provider list:"
+CORECFG_YES="Yes"
+CORECFG_NO="No"
+CORECFG_NO_BACK="No, return"
+CORECFG_INPUT_ALNUM="Please input letter or number"
+CORECFG_INPUT="Please enter"
+CORECFG_FILL_REQUIRED="Please complete required fields first!"
+CORECFG_START_APPLY="Start service to apply config now?"
+CORECFG_PROVIDER_SUPPORT="Supports adding subscription/share link/local file as provider"
+CORECFG_SET_NAME="Set \033[36mname/alias\033[0m\t"
+CORECFG_SET_LINK="Set \033[32mlink/path\033[0m:\t"
+CORECFG_SET_OVERRIDE="Set \033[33mlocal generation override\033[0m"
+CORECFG_SAVE_PROVIDER="\033[36mSave this provider\033[0m"
+CORECFG_DEL_PROVIDER="\033[31mDelete this provider\033[0m"
+CORECFG_MORE_CONFIG_HINT="For detailed settings below, go to corresponding feature page."
+CORECFG_GEN_LOCAL_ONE="\033[32mLocal generate\033[0m config with this provider only"
+CORECFG_GEN_ONLINE_ONE="\033[33mOnline generate\033[0m config with this provider only"
+CORECFG_GET_ONLINE_DIRECT="Fetch this config online directly (without conversion)"
+CORECFG_USE_DIRECT="Use this file directly as config (without local generation)"
+CORECFG_NAME_HINT="Note:\nName/alias cannot duplicate, cannot be pure digits, and should not be too long!"
+CORECFG_INPUT_NAME="Please input name/alias"
+CORECFG_OR_BACK="or input 0 to return"
+CORECFG_LINK_HINT1="\033[33mSubscription link\033[0m:\nClash config subscription URL starting with https/http"
+CORECFG_LINK_HINT2="\033[36mShare link\033[0m:"
+CORECFG_LINK_HINT3="\033[33mLocal file\033[0m:\nMust be placed under "
+CORECFG_LINK_HINT4=""
+CORECFG_LINK_HINT5="\033[36mBase64 \033[0m:\nPlease write to local file directly"
+CORECFG_INPUT0_BACK="Input 0 to return"
+CORECFG_SELECT_FILE_OR_LINK="Select file or input link"
+CORECFG_INPUT_LINK="Please input link directly"
+CORECFG_DANGER1="Warning:\nThis feature is incompatible with skip certificate verification"
+CORECFG_DANGER2="Please make sure you fully understand what you are doing"
+CORECFG_DANGER_CONFIRM="I confirm I can troubleshoot by myself"
+CORECFG_INTERVAL1="Set \033[33mhealth-check interval\033[0m:\t"
+CORECFG_INTERVAL2="Set \033[36mauto-update interval\033[0m:\t"
+CORECFG_MIN="min"
+CORECFG_HOUR="hour"
+CORECFG_SET_UA="Set \033[33mbrowser UA\033[0m:\t"
+CORECFG_SET_EXCLUDE="Set \033[31mexclude regex\033[0m:\t"
+CORECFG_SET_INCLUDE="Set \033[32minclude regex\033[0m:\t"
+CORECFG_CUR_INTERVAL="Current health-check interval:"
+CORECFG_INPUT_INTERVAL1="Input health-check interval (minutes)"
+CORECFG_RESET_INTERVAL1="or input r to reset to default (3 min)"
+CORECFG_INPUT_INTERVAL2="Input auto-update interval (hours)"
+CORECFG_RESET_INTERVAL2="or input r to reset to default (12 hours)"
+CORECFG_CUR_UA_NONE="Current browser UA: none"
+CORECFG_CUR_UA="Current browser UA: "
+CORECFG_INPUT_UA="Input browser UA"
+CORECFG_RESET_UA="or input r to reset UA to default (clash.meta)"
+CORECFG_CUR_EXCLUDE_NONE="Current exclude rule: none"
+CORECFG_CUR_EXCLUDE="Current exclude rule: "
+CORECFG_INPUT_EXCLUDE="Input exclude keyword(s) (regex supported, no spaces)"
+CORECFG_CLEAR_EXCLUDE="or input c to clear exclude rule"
+CORECFG_CUR_INCLUDE_NONE="Current include rule: none"
+CORECFG_CUR_INCLUDE="Current include rule: "
+CORECFG_INPUT_INCLUDE="Input include keyword(s) (regex supported, no spaces)"
+CORECFG_CLEAR_INCLUDE="or input c to clear include rule"
diff --git a/scripts/lang/en/7_gateway.lang b/scripts/lang/en/7_gateway.lang
new file mode 100644
index 00000000..f74107cf
--- /dev/null
+++ b/scripts/lang/en/7_gateway.lang
@@ -0,0 +1,97 @@
+GW_TITLE="Access & Control Menu"
+GW_WARN="Notice: "
+GW_FW_VPS_HINT="If running on a VPS, also allow related ports in your VPS security policy."
+GW_FW_PORT_LIMIT="Up to 10 allowed ports are supported. Please remove some first."
+GW_INPUT_ALLOW_PORT="Enter the port to allow"
+GW_OK="Done"
+GW_CORE_UNSUPPORTED=" core does not support this feature yet, please switch core first!"
+GW_TG_DONE_PREFIX="Telegram bot setup completed! Use"
+GW_TG_DONE_SUFFIX="to open the function menu!"
+GW_SET="Configured"
+GW_BOUND="Bound"
+GW_INPUT_PORT_DEL0="Enter port (0 to delete)"
+GW_INPUT_WSPATH="Enter ws-path (0 to delete)"
+GW_INPUT_UUID="Enter UUID (0 to delete)"
+GW_INPUT_HOST="Enter your public IP (v4/v6) or domain"
+GW_SHARE_LINK_HINT="Your share link (do not share casually):"
+GW_MENU_FW_WAN="Configure WAN Firewall"
+GW_MENU_TG_BOT="Configure Telegram Control Bot"
+GW_MENU_DDNS="Configure DDNS Domain"
+GW_MENU_VMESS="Custom Public Vmess Inbound"
+GW_MENU_SHADOWSOCKS="Custom Public ShadowSocks Inbound"
+GW_MENU_TS="Configure Tailscale Intranet (Singbox only)"
+GW_MENU_WG="Configure Wireguard Client (Singbox only)"
+GW_FW_STOP_WARN="WAN firewall requires stopping the service first"
+GW_CONFIRM_CONTINUE="Continue?"
+GW_YES="Yes"
+GW_NO="No"
+GW_NO_BACK="No, back to previous menu"
+GW_FW_MANUAL_PORTS="Manual allowed ports: "
+GW_FW_AUTO_PORTS="Auto allowed ports: "
+GW_FW_DEFAULT_BLOCK="Default blocked ports: "
+GW_FW_TOGGLE="Enable/Disable WAN firewall: "
+GW_FW_ADD_PORT="Add allowed ports (can include default blocked ports)"
+GW_FW_REMOVE_PORT="Remove a specific manual port"
+GW_FW_CLEAR_PORTS="Clear all manual allowed ports"
+GW_FW_DISABLE_CONFIRM="Confirm disabling firewall?"
+GW_FW_DISABLE_RISK="This can pose a serious security risk!"
+GW_ERR_DUP_PORT="Invalid input! Do not add duplicates!"
+GW_ERR_PORT_RANGE="Invalid input! Enter a valid number (1-65535)!"
+GW_ERR_INPUT="Invalid input!"
+GW_INPUT_REMOVE_PORT="Enter the port to remove"
+GW_INPUT_0_BACK="Or enter 0 to go back"
+GW_ERR_PORT_NOT_FOUND="Please enter a port that was added!"
+GW_TG_CMD_MENU="Open ShellCrash menu"
+GW_TG_CMD_HELP="View help"
+GW_TG_WARN="Due to network conditions, this bot only runs when the service is started!"
+GW_TG_TOGGLE="Enable/Disable TG-BOT service"
+GW_TG_BIND="TG-BOT binding"
+GW_TG_MENUPUSH="Push menu on start"
+GW_TG_BIND_FIRST="Please bind TG-BOT first!"
+GW_TG_BOUND_DETECTED="Detected an existing TG push bot binding"
+GW_TG_USE_DIRECT="Use it directly?"
+GW_INBOUND_WARN_PORT="The configured port will be added to the WAN firewall and allowed automatically!"
+GW_INBOUND_WARN_BASIC="This script provides basic features only. Use custom config for more needs!"
+GW_INBOUND_WARN_ILLEGAL="Do not use it for illegal proxying. You are responsible for consequences!"
+GW_VMS_TOGGLE="Enable/Disable Vmess inbound"
+GW_SET_LISTEN_PORT="Set listen port:"
+GW_SET_WSPATH="Set WS-path (optional):"
+GW_SET_UUID="Set key-uuid:"
+GW_GEN_RANDOM_KEY="Generate random key"
+GW_SET_OBFS_HOST="Set obfs host (optional):"
+GW_GEN_SHARE_LINK="Generate share link"
+GW_FILL_REQUIRED="Please complete required settings first!"
+GW_ERR_WSPATH="Invalid path. It must start with '/'."
+GW_ERR_UUID="Invalid UUID format. Re-enter or use random generation."
+GW_INPUT_OBFS_HOST="Enter obfs host (0 to delete)"
+GW_SS_TOGGLE="Enable/Disable ShadowSocks inbound"
+GW_SS_SELECT_CIPHER="Select cipher to use:"
+GW_SS_SET_PWD="Set password:"
+GW_SS_2022_NOTE_HEADER=" - - - - - - -\033[31mNotice\033[0m- - - - - - -"
+GW_SS_2022_REQUIRE=" 2022 ciphers require a randomly generated password!"
+GW_SS_2022_PASSWORD_ONLY="2022 ciphers require a script-generated password!"
+GW_TS_WARN="The default core is built without the Tailscale module to save memory.\nPlease switch to a full custom core if you need it!"
+GW_TS_KEY_URL="Create key:\033[32;4mhttps://login.tailscale.com/admin/settings/keys\033[0m"
+GW_TS_ALLOW_URL="Allow advertised routes for non-local targets:\033[32;4mhttps://login.tailscale.com\033[0m"
+GW_TS_SUBNET_EXIT_HINT="For non-local targets, use Subnet or EXIT-NODE mode in the client"
+GW_TS_TOGGLE="Enable/Disable Tailscale service"
+GW_TS_SET_AUTHKEY="Set Auth Key"
+GW_TS_SUBNET="Advertise subnet routes"
+GW_TS_EXIT_NODE="Advertise all traffic (EXIT-NODE)"
+GW_TS_HOSTNAME="Set device name (optional)"
+GW_TS_SET_KEY_FIRST="Please set the Auth Key first!"
+GW_TS_INPUT_KEY="Enter Auth Key (0 to delete)"
+GW_TS_EXITNODE_WARN="The official exitnode DNS has a bug. Either enable domain sniffing and disable Tailscale DNS,\nor set Globalname servers to this device subnet IP in the web UI and enable override."
+GW_TS_INPUT_NAME="Enter the device name to show in Tailscale"
+GW_WG_WARN="The default core is built without the WireGuard module to save memory.\nPlease switch to a full custom core if you need it!"
+GW_WG_TOGGLE="Enable/Disable Wireguard service"
+GW_WG_SET_ENDPOINT="Set Endpoint address:"
+GW_WG_SET_ENDPOINT_PORT="Set Endpoint port:"
+GW_WG_SET_PUBLIC="Set PublicKey:"
+GW_WG_SET_PRESHARED="Set PresharedKey:"
+GW_WG_SET_PRIVATE="Set PrivateKey:"
+GW_WG_SET_IPV4="Set IPv4 address:"
+GW_WG_SET_IPV6="Optional IPv6 address:"
+GW_INPUT_TEXT_DEL0="Enter value (Enter or 0 to delete)"
+GW_INPUT_PLAIN="Enter"
+GW_INPUT_PWD_DEL0="Enter password (0 to delete)"
diff --git a/scripts/lang/en/8_tools.lang b/scripts/lang/en/8_tools.lang
new file mode 100644
index 00000000..df64d1c0
--- /dev/null
+++ b/scripts/lang/en/8_tools.lang
@@ -0,0 +1,156 @@
+TOOLS_TITLE="Tools & Optimization"
+TOOLS_SSH_DISABLE="Disable"
+TOOLS_SSH_ENABLE="Enable"
+TOOLS_ERR_PORT="Invalid input! Please enter a valid number (1000-65535)!"
+TOOLS_ERR_PORT_OCCUPIED="This port is occupied by another process, please try another one!"
+TOOLS_SSH_SET_OK="Set successfully, please re-enable WAN SSH access!"
+TOOLS_SSH_ENABLED="WAN SSH access enabled!"
+TOOLS_SSH_DISABLED="WAN SSH access disabled!"
+TOOLS_DISABLE="Disable"
+TOOLS_ENABLE="Enable"
+TOOLS_CONFIGURED="Configured"
+TOOLS_SSH_ONLY_OPENWRT="This feature only works on OpenWrt devices and does not depend on services"
+TOOLS_SSH_UNSUPPORTED_SYSTEM="This feature does not support mirrored systems like Redmi AX6S. Do not try it!"
+TOOLS_SSH_PORT_ITEM_PREFIX="1) \033[32mChange\033[0m WAN SSH port:"
+TOOLS_SSH_PORT_ITEM_SUFFIX=""
+TOOLS_SSH_PASS_ITEM="2) \033[32mChange\033[0m SSH password (enter twice, then press Enter)"
+TOOLS_SSH_TOGGLE_ITEM_PREFIX="3) "
+TOOLS_SSH_TOGGLE_ITEM_SUFFIX=" WAN SSH access"
+TOOLS_PROMPT_PORT="Please enter a port number (1000-65535)> "
+TOOLS_WARN_COMPAT="This page may not be compatible with all Linux devices. Use at your own discretion!"
+TOOLS_DISK_USAGE="Disk usage / current directory:"
+TOOLS_MENU_TEST_ITEM="1) ShellCrash \033[33mTest Menu\033[0m"
+TOOLS_MENU_GUIDE_ITEM="2) ShellCrash \033[32mGetting Started\033[0m"
+TOOLS_MENU_LOG_ITEM="3) \033[36mLogs and Push Tools\033[0m"
+TOOLS_MENU_SSH_ITEM="4) \033[32mConfigure\033[0m WAN SSH access"
+TOOLS_MENU_MI_UPDATE_ITEM_PREFIX="5) "
+TOOLS_MENU_MI_UPDATE_ITEM_SUFFIX=" Xiaomi system auto-update"
+TOOLS_MENU_MI_AUTO_SSH_ITEM_PREFIX="6) Xiaomi device SSH hardening —— "
+TOOLS_MENU_MI_AUTO_SSH_ITEM_SUFFIX=""
+TOOLS_MENU_MI_TUN_FIX_ITEM_PREFIX="8) Xiaomi device Tun module repair —— "
+TOOLS_MENU_MI_TUN_FIX_ITEM_SUFFIX=""
+TOOLS_MI_UPDATE_MSG_PREFIX="Xiaomi router auto-update has been "
+TOOLS_MI_UPDATE_MSG_SUFFIX=". If it does not take effect, sync the setting in the official app!"
+TOOLS_UNSUPPORTED_DEVICE="Unsupported device!"
+TOOLS_FETCHING_SCRIPT="Fetching online script..."
+TOOLS_DOWNLOAD_FAIL="File download failed!"
+TOOLS_DISABLE_FIX_CONFIRM="Disable this feature and remove related patches?"
+TOOLS_YES="1) Yes"
+TOOLS_NO_BACK="0) No, return to previous menu"
+TOOLS_NO="0) No"
+TOOLS_SELECT_PROMPT="Please enter the number> "
+TOOLS_PATCH_REMOVED="Patch file removed. Reboot the device immediately to avoid errors!"
+TOOLS_TUN_WARN1="This feature needs to modify system files and does not guarantee zero risk!"
+TOOLS_TUN_WARN2="The collected Tun module may not suit your device!"
+TOOLS_ACCEPT_RISK="1) I understand and will take responsibility if anything goes wrong!"
+TOOLS_TUN_CONNECTING="Connecting to the server to fetch the Tun patch..."
+TOOLS_TUN_OK="Set successfully! Please restart the service!"
+TOOLS_TUN_FAIL="File download failed, please retry!"
+TOOLS_DEVICE_NOT_NEED="This device does not need this setting. Do not try it!"
+TOOLS_AUTO_SSH_WARN1="This feature hardens SSH using software commands and is not guaranteed to succeed 100%!"
+TOOLS_AUTO_SSH_WARN2="If you have issues, please report in the group:"
+TOOLS_AUTO_SSH_PWD_HINT1="Please enter the SSH password to restore (current password will not be affected)"
+TOOLS_AUTO_SSH_PWD_HINT2="(Press Enter to skip)"
+TOOLS_AUTO_SSH_INPUT="Please enter> "
+TOOLS_LOG_TG_PREFIX="1) Telegram push\t——"
+TOOLS_LOG_TG_SUFFIX=""
+TOOLS_LOG_DEER_PREFIX="2) PushDeer push\t——"
+TOOLS_LOG_DEER_SUFFIX=""
+TOOLS_LOG_BARK_PREFIX="3) Bark push-IOS\t——"
+TOOLS_LOG_BARK_SUFFIX=""
+TOOLS_LOG_PO_PREFIX="4) Passover push\t——"
+TOOLS_LOG_PO_SUFFIX=""
+TOOLS_LOG_PP_PREFIX="5) PushPlus push\t——"
+TOOLS_LOG_PP_SUFFIX=""
+TOOLS_LOG_SYNO_PREFIX="6) SynoChat push\t——"
+TOOLS_LOG_SYNO_SUFFIX=""
+TOOLS_LOG_GOTIFY_PREFIX="7) Gotify push\t ——"
+TOOLS_LOG_GOTIFY_SUFFIX=""
+TOOLS_LOG_VIEW="a) View \033[36mruntime logs\033[0m"
+TOOLS_LOG_TASK_PREFIX="b) Push task logs\t——"
+TOOLS_LOG_TASK_SUFFIX=""
+TOOLS_LOG_DEVICE_PREFIX="c) Set device name\t——"
+TOOLS_LOG_DEVICE_SUFFIX=""
+TOOLS_LOG_CLEAR="d) Clear log files"
+TOOLS_CONFIRM_CLOSE_TG="Are you sure you want to disable TG log push?"
+TOOLS_CONFIRM_CLOSE_DEER="Are you sure you want to disable PushDeer log push?"
+TOOLS_CONFIRM_CLOSE_BARK="Are you sure you want to disable Bark log push?"
+TOOLS_CONFIRM_CLOSE_PO="Are you sure you want to disable Pushover log push?"
+TOOLS_CONFIRM_CLOSE_PP="Are you sure you want to disable PushPlus log push?"
+TOOLS_CONFIRM_CLOSE_SYNO="Are you sure you want to disable SynoChat log push?"
+TOOLS_CONFIRM_CLOSE_GOTIFY="Are you sure you want to disable Gotify log push?"
+TOOLS_BOT_PUBLIC="1) Use public bot\t——No kernel service required"
+TOOLS_BOT_PRIVATE="2) Use private bot\t——Requires extra application"
+TOOLS_PUSHDEER_SELECT_SERVER="Please choose the PushDeer server type:"
+TOOLS_PUSHDEER_OFFICIAL="1) Official server (api2.pushdeer.com)"
+TOOLS_PUSHDEER_CUSTOM="2) Self-hosted server"
+TOOLS_PUSHDEER_CUSTOM_URL_HINT="Please enter the self-hosted PushDeer server address (without /message/push)"
+TOOLS_PUSHDEER_CUSTOM_URL_EXAMPLE="Example: \033[36mhttps://push.example.com\033[0m"
+TOOLS_PUSHDEER_CUSTOM_URL_INPUT="Please enter the server address directly"
+TOOLS_OR_BACK="Or enter 0 to return to the previous menu"
+TOOLS_PUSHDEER_INSTALL1="1. First go to \033[32;4mhttp://www.pushdeer.com/official.html\033[0m to scan and install the quick app or download the app"
+TOOLS_PUSHDEER_INSTALL2="2. Open the quick app/app and finish logging in"
+TOOLS_PUSHDEER_INSTALL3="3. Switch to the \"Device\" tab, tap the plus in the top-right corner, and register this device"
+TOOLS_PUSHDEER_INSTALL4="4. Switch to the \"Secret\" tab, tap the plus in the top-right corner, create a secret, and copy it"
+TOOLS_PUSHDEER_SECRET_HINT="Please enter the secret you copied"
+TOOLS_PUSHDEER_OK="PushDeer log push setup completed!"
+TOOLS_BARK_WARN="Bark push only supports iOS. Use another push method on other platforms!"
+TOOLS_BARK_INSTALL="Please install the Bark iOS client and find the dedicated push link in the app"
+TOOLS_BARK_URL_HINT="Please enter your Bark push link directly"
+TOOLS_BARK_OK="Bark log push setup completed!"
+TOOLS_PUSHOVER_REG="Please register at \033[32;4mhttps://pushover.net/\033[0m and get the \033[36mUser Key\033[0m"
+TOOLS_PUSHOVER_USERKEY_HINT="Please enter your User Key directly"
+TOOLS_PUSHOVER_VERIFY="Please check your registration email and complete account verification"
+TOOLS_PUSHOVER_VERIFIED="I have completed verification"
+TOOLS_PUSHOVER_VERIFY_PROMPT="I have completed verification (1/0)> "
+TOOLS_PUSHOVER_TOKEN_BUILD="Generate an \033[36mAPI Token\033[0m at \033[32;4mhttps://pushover.net/apps/build\033[0m"
+TOOLS_PUSHOVER_TOKEN_HINT="Please enter your API Token"
+TOOLS_PUSHOVER_OK="Passover log push setup completed!"
+TOOLS_PUSHPLUS_REG="Please register at \033[32;4mhttps://www.pushplus.plus/push1.html\033[0m and get the \033[36mtoken\033[0m"
+TOOLS_PUSHPLUS_TOKEN_HINT="Please enter your token directly"
+TOOLS_PUSHPLUS_OK="PushPlus log push setup completed!"
+TOOLS_SYNOCHAT_URL_HINT="Please enter your Synology DSM home address"
+TOOLS_SYNOCHAT_TOKEN_HINT="Please enter your Synology Chat token"
+TOOLS_SYNOCHAT_USERID_HINT="Get the user_id via \"your NAS address/webapi/entry.cgi?api=SYNO.Chat.External&method=user_list&version=2&token=YOUR_TOKEN\""
+TOOLS_SYNOCHAT_USERID_INPUT="Please enter your user_id> "
+TOOLS_SYNOCHAT_OK="SynoChat log push setup completed!"
+TOOLS_GOTIFY_REG="Please obtain the push URL from your Gotify server"
+TOOLS_GOTIFY_FORMAT="Format example: https://gotify.example.com/message?token=your_app_token"
+TOOLS_GOTIFY_URL_HINT="Please enter your Gotify push URL directly"
+TOOLS_LOG_NOT_FOUND="No related log found!"
+TOOLS_DEVICE_NAME_HINT="Please enter a custom push name for this device"
+TOOLS_DEVICE_NAME_BACK="Or press Enter directly to return to the previous menu"
+TOOLS_LOG_CLEARED="Runtime logs and task logs have been cleared!"
+TOOLS_TEST_MENU_TITLE="This is the test command menu"
+TOOLS_TEST_MENU_HINT="If you encounter issues, run the relevant command and submit a screenshot to the issue or TG group"
+TOOLS_TEST_ITEM_1="1) Run the kernel in Debug mode"
+TOOLS_TEST_ITEM_2="2) Check system DNS port (:53) usage "
+TOOLS_TEST_ITEM_3="3) Test SSL encryption (aes-128-gcm) benchmark"
+TOOLS_TEST_ITEM_4="4) View ShellCrash routing rules"
+TOOLS_TEST_ITEM_5="5) View the first 40 lines of the kernel config file"
+TOOLS_TEST_ITEM_6="6) Test proxy server connectivity (google.tw)"
+TOOLS_NETSTAT_HINT="You can use \033[44m netstat -ntulp |grep xxx \033[0m to query any (xxx) port"
+TOOLS_FW_TITLE="----------------Local Firewall---------------------"
+TOOLS_PROXY_NOTE="Note: depends on curl (wget is not supported), and the test result is not guaranteed to be accurate!"
+TOOLS_PROXY_OK="Connection successful! Response time: "
+TOOLS_PROXY_TIMEOUT="Connection timed out! Please retry or check the node configuration!"
+TOOLS_DEBUG_WARN1="Note: Debug mode will stop the original kernel service"
+TOOLS_DEBUG_WARN2_PREFIX="Background log path: "
+TOOLS_DEBUG_WARN2_SUFFIX=""
+TOOLS_DEBUG_WARN3="For long-running background monitoring, error is recommended as the log level to avoid oversized files!"
+TOOLS_DEBUG_WARN4="You can also use: \033[33mcrash -s debug 'warning'\033[0m to select another log level"
+TOOLS_DEBUG_ITEM_1_PREFIX="1) Only test the availability of the "
+TOOLS_DEBUG_ITEM_1_SUFFIX=" config file"
+TOOLS_DEBUG_ITEM_2_PREFIX="2) Run the "
+TOOLS_DEBUG_ITEM_2_SUFFIX=" config file in foreground without firewall hijacking (use Ctrl+C to stop manually)"
+TOOLS_DEBUG_ITEM_3="3) Run the full startup flow in background with firewall hijacking, log level: \033[31merror\033[0m"
+TOOLS_DEBUG_ITEM_4="4) Run the full startup flow in background with firewall hijacking, log level: \033[32minfo\033[0m"
+TOOLS_DEBUG_ITEM_5="5) Run the full startup flow in background with firewall hijacking, log level: \033[33mdebug\033[0m"
+TOOLS_DEBUG_ITEM_6_PREFIX="6) Run the full startup flow in background with firewall hijacking and print error logs to flash: "
+TOOLS_DEBUG_ITEM_6_SUFFIX=""
+TOOLS_DEBUG_ITEM_8="8) Run the full startup flow in background, print execution errors and inspect context, then close the process"
+TOOLS_DEBUG_ITEM_9_PREFIX="9) Merge the json files under "
+TOOLS_DEBUG_ITEM_9_SUFFIX=" into "
+TOOLS_FLASH_WARN="Frequent flash writes will shorten flash lifespan. Unless you are dealing with a bug that would otherwise crash or reboot the device, do not use this feature!"
+TOOLS_FLASH_CONFIRM="Confirm enabling this feature?"
+TOOLS_MERGE_OK="Merged successfully!"
diff --git a/scripts/lang/en/9_upgrade.lang b/scripts/lang/en/9_upgrade.lang
new file mode 100644
index 00000000..5e91c1e7
--- /dev/null
+++ b/scripts/lang/en/9_upgrade.lang
@@ -0,0 +1,296 @@
+UPG_ERR_TRY_OTHER_SOURCE="Please switch to another source and try downloading again!"
+UPG_ERR_LOCAL_INSTALL="Or refer to \033[32;4mhttps://juewuy.github.io/bdaz\033[0m for local installation!"
+UPG_TITLE="Update & Support"
+UPG_CUR_DIR_SPACE="Current directory"
+UPG_LOW_SPACE_HINT="Low free space in current directory, consider enabling low-flash mode!"
+UPG_MENU_SCRIPT="Update "
+UPG_MENU_SCRIPT_NAME="script"
+UPG_MENU_CORE="Switch/Update "
+UPG_MENU_CORE_NAME="core"
+UPG_MENU_GEO="Install/Update local "
+UPG_MENU_GEO_NAME="database files"
+UPG_MENU_DB="Install/Update local "
+UPG_MENU_DB_NAME="Dashboard"
+UPG_MENU_CRT="Install/Update local "
+UPG_MENU_CRT_NAME="certificates"
+UPG_MENU_PAC="Auto proxy view"
+UPG_MENU_SOURCE="Switch "
+UPG_MENU_SOURCE_NAME="source and branch"
+UPG_MENU_UNINSTALL="Uninstall ShellCrash"
+UPG_MENU_THANKS="Thanks list"
+UPG_PAC_LINK="PAC URL: "
+UPG_PAC_GUIDE="PAC guide: "
+UPG_THANKS_TITLE="Thanks to the following projects and developers!"
+UPG_THANKS_SPECIAL="Special thanks: \033[36mall contributors and sponsors!\033[0m"
+UPG_CHECKING="Checking updates..."
+UPG_CHECK_OK="Update check succeeded"
+UPG_CHECK_FAIL="Update check failed! Please switch source and retry!"
+UPG_DOWNLOAD_FAIL="Download failed!"
+UPG_EXTRACTING="Extracting files..."
+UPG_EXTRACT_FAIL="Extraction failed!"
+UPG_SCRIPT_OK="Script update succeeded!"
+UPG_SCRIPT_WARN="Note: service will be stopped during update!"
+UPG_SCRIPT_CUR_VER="Current script version: "
+UPG_SCRIPT_NEW_VER="Latest script version: "
+UPG_UPDATE_NOW="Update now"
+UPG_SCRIPT_MGR_OK="Manager script updated successfully!"
+UPG_CPUCORE_HINT1="Use only when CPU architecture detection fails or core cannot run!"
+UPG_CPUCORE_HINT2="Not sure how to get core arch?"
+UPG_CPUCORE_HINT3="Refer to: "
+UPG_CPUCORE_LIST="Available online CPU architectures:"
+UPG_CPUCORE_ERR="Please enter a valid CPU architecture!"
+UPG_CORETYPE_CONFIRM="Please confirm custom core type:"
+UPG_CORE_SWITCH_PREFIX="Switched from "
+UPG_CORE_SWITCH_MID=" to "
+UPG_CORE_SWITCH_SUFFIX=" core"
+UPG_CORE_SWITCH_WARN="Geo DB and yaml/json configs are not compatible between the two cores"
+UPG_CORE_SWITCH_KEEP="Keep related database files?"
+UPG_KEEP="Keep"
+UPG_NOT_KEEP="Do not keep"
+UPG_PAC_LINK_TEXT="PAC URL: "
+UPG_PAC_GUIDE_TEXT="PAC guide: "
+UPG_THANKS_PROJECTS="Thanks to the following projects and developers!"
+UPG_THANKS_SPECIAL_TEXT="Special thanks: \033[36mall contributors and sponsors!\033[0m"
+UPG_GETTING_UPDATE="Checking updates..."
+UPG_SCRIPT_CUR_VER_TEXT="Current script version: "
+UPG_SCRIPT_NEW_VER_TEXT="Latest script version: "
+UPG_UPDATE_NOW_TEXT="Update now"
+UPG_CPUCORE_HINT1_TEXT="Use only when CPU architecture detection fails or core cannot run!"
+UPG_CPUCORE_HINT2_TEXT="Not sure how to get core arch?"
+UPG_CPUCORE_HINT3_TEXT="Refer to: "
+UPG_CPUCORE_LIST_TEXT="Available online CPU architectures:"
+UPG_CORETYPE_CONFIRM_TEXT="Please confirm custom core type:"
+UPG_CORE_SWITCH_KEEP_TEXT="Keep related database files?"
+UPG_KEEP_TEXT="Keep"
+UPG_NOT_KEEP_TEXT="Do not keep"
+UPG_GETTING_CORE_TEXT_PREFIX="Fetching "
+UPG_GETTING_CORE_TEXT_SUFFIX=" core files online..."
+UPG_CORE_DOWNLOAD_OK_TEXT_PREFIX=""
+UPG_CORE_DOWNLOAD_OK_TEXT_SUFFIX=" core downloaded successfully!"
+UPG_CORE_DOWNLOAD_FAIL_TEXT="Core file download failed!"
+UPG_CORE_DOWNLOAD_VERIFY_FAIL_TEXT="Core file downloaded, but verification failed"
+UPG_CORE_DOWNLOAD_VERIFY_HINT_TEXT="Please try selecting a CPU version manually"
+UPG_CORE_LINK_TEXT="Fetching core file links..."
+UPG_CORE_INFO_TITLE="Core version: "
+UPG_CORE_INFO_TIME1="Release time: "
+UPG_CORE_INFO_TIME2="Updated: "
+UPG_CORE_INFO_SELECT="Please confirm the core info and choose:"
+UPG_CORE_NOT_FOUND="No available core found. The developer may not have built a binary for this CPU architecture!"
+UPG_CORE_CHECK_FAIL_HINT="Search failed. Please try again after the service starts!"
+UPG_CUSTOM_CORE_SOURCE="This core is usually collected from the internet. Thanks to the developers!"
+UPG_CUSTOM_CORE_WARN="Custom cores have not been fully adapted. Please fix issues yourself if they occur!"
+UPG_CUSTOM_CORE_TASK_WARN="Custom cores support scheduled tasks but do not support low-flash mode!"
+UPG_CUSTOM_CORE_NET_WARN="If you encounter network errors, start the ShellCrash service first!"
+UPG_CUSTOM_CORE_CURRENT="Current core: "
+UPG_CUSTOM_CORE_SELECT="Please choose the core you want to use:"
+UPG_CUSTOM_CORE_MENU_OFFICIAL=" official core"
+UPG_CUSTOM_CORE_MENU_ALPHA=" core (supports Smart strategy)"
+UPG_CUSTOM_CORE_MENU_MULTI=" multi-version core"
+UPG_CUSTOM_CORE_LINK_HINT="Please enter the custom core URL"
+UPG_CUSTOM_CORE_LINK_HINT2="(must end with .tar.gz, .upx, or .gz)"
+UPG_CUSTOM_CORE_LINK_HINT3="Or enter 0 to return to the previous menu"
+UPG_CUSTOM_CORE_LINK_MENU="Use custom core URL"
+UPG_ZIPTYPE_TITLE="Please choose the core branch and compression method:"
+UPG_ZIPTYPE_1="1) \033[36mMinimal release build, upx compressed\033[0m"
+UPG_ZIPTYPE_1_HINT="Gvisor, Tailscale, Wireguard, and NaiveProxy are not supported"
+UPG_ZIPTYPE_2="2) \033[32mStandard release build, tar.gz compressed\033[0m"
+UPG_ZIPTYPE_2_HINT="Fully supports all built-in script features"
+UPG_ZIPTYPE_3="3) \033[33mFull alpha build, gz compressed\033[0m"
+UPG_ZIPTYPE_3_HINT="May use a bit more space; stability is self-tested"
+UPG_CORE_MENU_CURRENT="Current core: "
+UPG_CORE_MENU_SYS="Current CPU architecture: "
+UPG_CORE_MENU_LOCAL_HINT="If uploading locally, place .upx, .gz, or .tar.gz files in /tmp and rerun the crash command"
+UPG_CORE_MENU_SELECT="Please choose the core version to use:"
+UPG_CORE_MENU_1_PREFIX="1) \033[43;30mMihomo\033[0m: \033[32m"
+UPG_CORE_MENU_1_SUFFIX=" \033[32m(full meta core) highly compatible\033[0m \033[33mmore resource usage\033[0m"
+UPG_CORE_MENU_2_PREFIX="2) \033[43;30mSingBoxR\033[0m: \033[32m"
+UPG_CORE_MENU_2_SUFFIX=" \033[32mfully featured\033[0m \033[33mreF1nd enhanced branch\033[0m"
+UPG_CORE_MENU_3_PREFIX="3) \033[43;30mSingBox\033[0m: \033[32m"
+UPG_CORE_MENU_3_SUFFIX=" \033[32mlower resource usage\033[0m \033[33mproviders are not supported\033[0m"
+UPG_CORE_MENU_4_PREFIX="4) \033[43;30mClash\033[0m: \033[32m"
+UPG_CORE_MENU_4_SUFFIX=" \033[32mlow resource usage\033[0m \033[33munsafe, maintenance stopped\033[0m"
+UPG_CORE_MENU_5_PREFIX="5) Switch branch and compression method: \033[32m"
+UPG_CORE_MENU_5_SUFFIX="\033[0m"
+UPG_CORE_MENU_6_PREFIX="6) \033[36mUse custom core\033[0m "
+UPG_CORE_MENU_6_SUFFIX=""
+UPG_CORE_MENU_7="7) \033[32mUpdate current core\033[0m"
+UPG_CORE_MENU_9="9) Manually specify CPU architecture"
+UPG_GEO_GETTING="Fetching database files from the server..."
+UPG_GEO_OK_PREFIX=""
+UPG_GEO_OK_SUFFIX=" database file downloaded successfully!"
+UPG_GEO_LINKING="Fetching database files..."
+UPG_GEO_FINDING="Searching for updatable database files..."
+UPG_GEO_SELECT="Please choose the database file to update:"
+UPG_GEO_NO_RESULT="Search failed. Please try again after the service starts!"
+UPG_GEO_CUSTOM_HINT="These database files are usually collected from the internet. Thanks to the developers!"
+UPG_GEO_CUSTOM_HINT2="Please click or copy the link to visit the project page for details!"
+UPG_GEO_CUSTOM_HINT3="Custom databases do not support scheduled tasks or low-flash mode!"
+UPG_GEO_CUSTOM_HINT4="If you encounter network errors, start the ShellCrash service first!"
+UPG_GEO_SOURCE_SELECT="Please choose the database source:"
+UPG_GEO_LOCAL_ONLY1="(Clash/Mihomo only)"
+UPG_GEO_LOCAL_ONLY2="(SingBox-srs only)"
+UPG_GEO_LOCAL_ONLY3="(Mihomo-mrs only)"
+UPG_GEO_LOCAL_ONLY4="(Clash-GeoIP only)"
+UPG_GEO_CUSTOM_LINK="Custom database link"
+UPG_GEO_CLEAN_HINT1_PREFIX="This will clean all database files under "
+UPG_GEO_CLEAN_HINT1_SUFFIX=" and /ruleset!"
+UPG_GEO_CLEAN_HINT2="After cleaning, starting the service will automatically download the required files"
+UPG_GEO_CLEAN_CONFIRM="Confirm cleanup"
+UPG_GEO_CLEAN_OK="All database files have been cleaned!"
+UPG_DB_GETTING="Connecting to the server to fetch installation files..."
+UPG_DB_DOWNLOAD_OK="Download succeeded, extracting files..."
+UPG_DB_OK="Panel installed successfully!"
+UPG_DB_REFRESH_HINT="If it does not take effect, use Ctrl+F5 to force-refresh the browser!"
+UPG_DB_INSTALLED="A local panel is already installed"
+UPG_DB_UPGRADE="Upgrade / overwrite install"
+UPG_DB_CANCEL="Installation cancelled"
+UPG_DB_DIR_SELECT="Please choose the panel install directory:"
+UPG_DB_DIR_1_PREFIX="1) Install in "
+UPG_DB_DIR_1_SUFFIX="/ui"
+UPG_DB_DIR_2="2) Install in /www/clash"
+UPG_DB_TITLE="Install the dashboard management panel locally"
+UPG_DB_TITLE2="The management panel opens faster and is more stable"
+UPG_DB_SELECT="Please choose the panel installation type:"
+UPG_DB_WIP=" - - - - - - -Maintenance - - - - - - -"
+UPG_DB_OLD=" - - - - - -Maintenance stopped - - - - - -"
+UPG_DB_INSTALL_1="1) Install \033[32mzashboard panel\033[0m (about 2.2mb)"
+UPG_DB_INSTALL_2="2) Install \033[32mMetaXD panel\033[0m (about 1.5mb)"
+UPG_DB_INSTALL_3="3) Install \033[32mYacd-Meta modified panel\033[0m (about 1.7mb)"
+UPG_DB_INSTALL_4="4) Install \033[32mbasic panel\033[0m (about 500kb)"
+UPG_DB_INSTALL_5="5) Install \033[32mMeta basic panel\033[0m (about 800kb)"
+UPG_DB_INSTALL_6="6) Install \033[32mYacd panel\033[0m (about 1.1mb)"
+UPG_DB_UNINSTALL="9) \033[31mUninstall local panel\033[0m"
+UPG_DB_UNINSTALL_CONFIRM="Uninstall the local panel?"
+UPG_DB_UNINSTALL_YES="1) Confirm uninstall"
+UPG_DB_UNINSTALL_OK="Panel has been uninstalled!"
+UPG_CRT_DB_OK="Certificate installed successfully!"
+UPG_CRT_TITLE1="Install / update local root certificate file (ca-certificates.crt)"
+UPG_CRT_TITLE2="Used to fix certificate verification errors, x509 errors, and similar issues"
+UPG_CRT_TITLE3="Do not use on devices without the above issues!"
+UPG_CRT_EXISTS="The system already has a root certificate file:"
+UPG_CRT_UPDATE="1) Overwrite update"
+UPG_CRT_INSTALL="1) Install now"
+UPG_CRT_BACK="0) Return to previous menu"
+UPG_CRT_WARN="This device may not have openssl installed, so certificate files cannot be installed!"
+UPG_SOURCE_CUR="Current version: "
+UPG_SOURCE_CUR2="Current source: "
+UPG_SOURCE_TITLE="Switch ShellCrash version and update source"
+UPG_SOURCE_SWITCH_STABLE="a) Switch to \033[32mstable\033[0m"
+UPG_SOURCE_SWITCH_MASTER="b) Switch to \033[36mpublic beta-master\033[0m"
+UPG_SOURCE_SWITCH_DEV="c) Switch to \033[33mdev\033[0m"
+UPG_SOURCE_CUSTOM="d) Custom source URL (for local or self-hosted sources)"
+UPG_SOURCE_ROLLBACK="e) \033[31mVersion rollback\033[0m"
+UPG_SOURCE_DEV_WARN1="The development branch has not been properly tested and may still contain many bugs!!!"
+UPG_SOURCE_DEV_WARN2="If you do not have enough patience or testing experience, do not use this version!"
+UPG_SOURCE_DEV_WARN3="Please join our discussion group: \033[36;4mhttps://t.me/ShellClash\033[0m"
+UPG_SOURCE_DEV_CONFIRM="Still switch to the development branch?"
+UPG_SOURCE_DEV_YES="1) Confirm switch"
+UPG_SOURCE_CUSTOM_HINT="Please enter the personal source path directly"
+UPG_SOURCE_CUSTOM_HINT2="Or enter 0 to return to the previous menu"
+UPG_SOURCE_CUSTOM_INPUT="Please enter the personal source path> "
+UPG_SOURCE_VER_GETTING="Fetching version information..."
+UPG_SOURCE_VER_OK="Version information fetched successfully"
+UPG_SOURCE_ROLLBACK_SELECT="Please select the specific version to roll back to:"
+UPG_SOURCE_ROLLBACK_FAIL="Failed to fetch rollback information. Please try another source!"
+UPG_SOURCE_ROLLBACK_NOTSUP="Current source does not support version rollback"
+UPG_SOURCE_ROLLBACK_HINT="Please try another installation source!"
+UPG_THANKS_ITEM_CLASH="Clash Developer: Dreamacro"
+UPG_THANKS_ITEM_SINGBOX="sing-box Developer: SagerNet"
+UPG_THANKS_ITEM_SINGBOX_URL="Project: https://github.com/SagerNet/sing-box"
+UPG_THANKS_ITEM_METACUBE="MetaCubeX Developer: MetaCubeX"
+UPG_THANKS_ITEM_METACUBE_URL="Project: https://github.com/MetaCubeX"
+UPG_THANKS_ITEM_YACD="YACD panel Developer: haishanh"
+UPG_THANKS_ITEM_YACD_URL="Project: https://github.com/haishanh/yacd"
+UPG_THANKS_ITEM_ZASH="Zashboard Developer: Zephyruso"
+UPG_THANKS_ITEM_ZASH_URL="Project: https://github.com/Zephyruso/zashboard"
+UPG_THANKS_ITEM_SUB="Subconverter Developer: tindy2013"
+UPG_THANKS_ITEM_SUB_URL="Project: https://github.com/tindy2013/subconverter"
+UPG_THANKS_ITEM_REF1ND="sing-box-reF1nd Developer: reF1nd"
+UPG_THANKS_ITEM_REF1ND_URL="Project: https://github.com/reF1nd/sing-box"
+UPG_THANKS_ITEM_DUSTIN="DustinWin Developer: DustinWin"
+UPG_THANKS_ITEM_DUSTIN_URL="Developer: https://github.com/DustinWin"
+UPG_CORE_GET_LINK_TITLE="Fetching core file links..."
+UPG_CUSTOM_CORE_NOTE1="Gvisor, Tailscale, Wireguard, and NaiveProxy are not supported"
+UPG_CORE_V1_PREFIX="1) \033[43;30mMihomo\033[0m: \033[32m"
+UPG_CORE_V1_SUFFIX=" \033[32m(full meta core) highly compatible\033[0m \033[33mmore resource usage\033[0m"
+UPG_CORE_V1_DOC="Docs: \033[36;4mhttps://wiki.metacubex.one\033[0m"
+UPG_CORE_V2_PREFIX="2) \033[43;30mSingBoxR\033[0m: \033[32m"
+UPG_CORE_V2_SUFFIX=" \033[32mfully featured\033[0m \033[33mreF1nd enhanced branch\033[0m"
+UPG_CORE_V2_DOC="Docs: \033[36;4mhttps://sing-boxr.dustinwin.cc.cd\033[0m"
+UPG_CORE_V3_PREFIX="3) \033[43;30mSingBox\033[0m: \033[32m"
+UPG_CORE_V3_SUFFIX=" \033[32mlower resource usage\033[0m \033[33mproviders are not supported\033[0m"
+UPG_CORE_V3_DOC="Docs: \033[36;4mhttps://sing-box.sagernet.org\033[0m"
+UPG_CORE_V4_PREFIX="4) \033[43;30mClash\033[0m: \033[32m"
+UPG_CORE_V4_SUFFIX=" \033[32mlow resource usage\033[0m \033[33munsafe, maintenance stopped\033[0m"
+UPG_CORE_V4_DOC="Docs: \033[36;4mhttps://lancellc.gitbook.io\033[0m"
+UPG_CORE_ASUS_WARN="The GeoSite.dat database used by Meta core may be deleted by the system on Asus devices, so it may not work!"
+UPG_GEO_FIND_TITLE="Searching for updatable database files..."
+UPG_GEO_SOURCE_TITLE="Please choose the database source:"
+UPG_GEO_LINK_HINT="Please enter the custom database URL> "
+UPG_GEO_CHOOSE_HINT="Note: Mihomo and SingBox database files are not interchangeable"
+UPG_GEO_LATEST="Latest online database version (synced daily): "
+UPG_GEO_CHOOSE="Please choose the Geo database file to update:"
+UPG_GEO_ITEM1="1) CN-IP bypass file (about 0.1mb)"
+UPG_GEO_ITEM2="2) CN-IPV6 bypass file (about 30kb)"
+UPG_GEO_ITEM3="3) Mihomo lite GeoIP_cn database (about 0.1mb)"
+UPG_GEO_ITEM4="4) Mihomo full GeoSite database (about 5mb)"
+UPG_GEO_ITEM5="5) Mihomo-mrs common package (about 1mb, use only if needed)"
+UPG_GEO_ITEM6="6) SingBox-srs common package (about 0.8mb, use only if needed)"
+UPG_GEO_ITEM8="8) \033[36mCustom database file\033[0m"
+UPG_GEO_ITEM9="9) \033[31mClean database files\033[0m"
+UPG_GEO_CLEAN_PROMPT="Confirm cleanup"
+UPG_GEO_CLEAN_WARN_PREFIX="This will clean all database files under "
+UPG_GEO_CLEAN_WARN_SUFFIX=" and /ruleset!"
+UPG_GEO_CLEAN_WARN2="After cleanup, start the service to download the required files automatically"
+UPG_GEO_CLEANED="All database files have been cleaned!"
+UPG_DB_CONNECTING="Connecting to the server to fetch installation files..."
+UPG_DB_INSTALLED_HINT="A local panel is already installed"
+UPG_DB_INSTALL_CANCEL="Installation cancelled"
+UPG_DB_DIR_TITLE="Please choose the panel install directory:"
+UPG_DB_DIR_1_TEXT_PREFIX="1) Install in "
+UPG_DB_DIR_1_TEXT_SUFFIX="/ui"
+UPG_DB_DIR_2_TEXT="2) Install in /www/clash"
+UPG_DB_INSTALL_TITLE="Install the dashboard management panel locally"
+UPG_DB_INSTALL_TITLE2="The management panel opens faster and is more stable"
+UPG_DB_INSTALL_SELECT="Please choose the panel installation type:"
+UPG_DB_INSTALL_MID=" - - - - - - -Maintenance - - - - - - -"
+UPG_DB_INSTALL_END=" - - - - - -Maintenance stopped - - - - - -"
+UPG_DB_INSTALL_4_TEXT="4) Install \033[32mbasic panel\033[0m (about 500kb)"
+UPG_DB_INSTALL_5_TEXT="5) Install \033[32mMeta basic panel\033[0m (about 800kb)"
+UPG_DB_INSTALL_6_TEXT="6) Install \033[32mYacd panel\033[0m (about 1.1mb)"
+UPG_DB_UNINSTALL_PROMPT="Uninstall the local panel?"
+UPG_DB_UNINSTALL_CONFIRM_TEXT="1) Confirm uninstall"
+UPG_DB_UNINSTALLED="Panel has been uninstalled!"
+UPG_CRT_CONNECTING="Connecting to the server to fetch installation files..."
+UPG_CRT_INSTALL_TITLE1="Install / update local root certificate file (ca-certificates.crt)"
+UPG_CRT_INSTALL_TITLE2="Used to fix certificate verification errors, x509 errors, and similar issues"
+UPG_CRT_INSTALL_TITLE3="Do not use on devices without the above issues!"
+UPG_CRT_EXIST_HINT="The system already has a root certificate file:"
+UPG_CRT_OVERWRITE="1) Overwrite update"
+UPG_CRT_NOW="1) Install now"
+UPG_CRT_NOT_USE="This device may not have openssl installed, so certificate files cannot be installed!"
+UPG_SOURCE_TITLE2="Switch ShellCrash version and update source"
+UPG_SOURCE_CUR_VER="Current version: "
+UPG_SOURCE_CUR_URL="Current source: "
+UPG_SOURCE_STABLE_TEXT="stable"
+UPG_SOURCE_MASTER_TEXT="beta"
+UPG_SOURCE_DEV_TEXT="dev"
+UPG_SOURCE_DEV_WARN4="The development branch has not been properly tested and may still contain many bugs!!!"
+UPG_SOURCE_DEV_WARN5="If you do not have enough patience or testing experience, do not use this version!"
+UPG_SOURCE_DEV_WARN6="Please join our discussion group: \033[36;4mhttps://t.me/ShellClash\033[0m"
+UPG_SOURCE_DEV_ASK="Still switch to the development branch?"
+UPG_SOURCE_DEV_CONFIRM_TEXT="1) Confirm switch"
+UPG_SOURCE_PATH_HINT="Please enter the personal source path directly"
+UPG_SOURCE_PATH_HINT2="Or enter 0 to return to the previous menu"
+UPG_SOURCE_PATH_INPUT="Please enter the personal source path> "
+UPG_SOURCE_GETTING_VER="Fetching version information..."
+UPG_SOURCE_GET_VER_OK="Version information fetched successfully"
+UPG_SOURCE_ROLLBACK_SELECT_TEXT="Please select the specific version to roll back to:"
+UPG_SOURCE_ROLLBACK_FAIL_TEXT="Failed to fetch rollback information. Please try another source!"
+UPG_SOURCE_ROLLBACK_NOTSUP_TEXT="Current source does not support version rollback"
+UPG_SOURCE_ROLLBACK_HINT_TEXT="Please try another installation source!"
+UPG_SOURCE_SWITCH_OK="Source switched successfully!"
+UPG_GEO_TYPE_LITE="lite"
+UPG_GEO_TYPE_FULL="global"
+UPG_SOURCE_UNSET="unset"
+UPG_SOURCE_ROLLBACK_TAG="(rollback)"
diff --git a/scripts/lang/en/bot_tg.lang b/scripts/lang/en/bot_tg.lang
new file mode 100644
index 00000000..0e86697e
--- /dev/null
+++ b/scripts/lang/en/bot_tg.lang
@@ -0,0 +1,68 @@
+BOT_TG_PRIVATE_HINT="Please apply for a Telegram bot via \033[32;4mhttps://t.me/BotFather\033[0m and get its \033[36mAPI TOKEN\033[0m first"
+BOT_TG_INPUT_TOKEN="Please enter your API TOKEN"
+BOT_TG_PRIVATE_TOP="Please send to \033[32myour bot\033[33m, NOT BotFather!\033[0m"
+BOT_TG_PUBLIC_HINT="Please message the bot: \033[32;4mhttps://t.me/ShellCrashtg_bot\033[0m"
+BOT_TG_SET_DONE="Telegram log push has been configured!"
+BOT_TG_CHATID_RETRY_PREFIX="Attempt"
+BOT_TG_CHATID_RETRY_SUFFIX="to get chat ID failed, retrying..."
+BOT_TG_SEND_KEY="Send this key:"
+BOT_TG_SENT_CONFIRM="I have sent it"
+BOT_TG_CHATID_FAIL="Unable to get chat ID. Please reconfigure or input ChatID manually!"
+BOT_TG_CHATID_MANUAL_HINT="Usually visit"
+BOT_TG_CHATID_MANUAL_HINT2="to find ChatID"
+BOT_TG_INPUT_CHATID="Please input ChatID manually"
+BOT_TG_CHATID_RECONFIG="Unable to get chat ID. Please reconfigure!"
+BOT_TG_CRON_NAME="TG_BOT watchdog"
+
+BOT_TG_HELP_GROUP="Group chat:"
+BOT_TG_HELP_PROJECT="Project:"
+BOT_TG_HELP_GUIDE="Guide:"
+BOT_TG_HELP_COFFEE="Buy me a coffee:"
+BOT_TG_HELP_AIRPORT="Partner provider:"
+BOT_TG_RUN_ON="🟢Running"
+BOT_TG_RUN_OFF="🟡Stopped"
+BOT_TG_WELCOME="Welcome to ShellCrash!"
+BOT_TG_SERVICE=" service "
+BOT_TG_MEM_USED="Memory usage: "
+BOT_TG_RUNNING_TIME="Running: "
+BOT_TG_SELECT_ACTION="Please choose:"
+BOT_TG_SELECT_FILE="Please choose file upload/download action:"
+BOT_TG_BTN_START="✈️ Enable redirect"
+BOT_TG_BTN_PURE="💧 Pure mode"
+BOT_TG_BTN_RESTART="🕹 Restart service"
+BOT_TG_BTN_LOG="📄 View logs"
+BOT_TG_BTN_TRANSFER="🔃 File transfer"
+BOT_TG_BTN_GET_LOG="📥 Download log"
+BOT_TG_BTN_GET_BAK="💾 Backup settings"
+BOT_TG_BTN_GET_CFG="⬇️ Download config"
+BOT_TG_BTN_UP_CORE="🪐 Upload core"
+BOT_TG_BTN_UP_BAK="🔄 Restore settings"
+BOT_TG_BTN_UP_CFG="⬆️ Upload config"
+BOT_TG_NO_CURL="⚠️ curl is missing on this device, only upload is supported!"
+BOT_TG_UPLOAD_OK="success! Service will restart soon!"
+BOT_TG_UPLOAD_FAIL="failed, please check file and retry!"
+BOT_TG_CORE_UPDATE="Core update "
+BOT_TG_CFG_RESTORED="Config restored, please restart service manually!"
+BOT_TG_RESTORE_FAIL="Restore failed while extracting backup, please retry!"
+BOT_TG_CFG_UPLOADED="Config uploaded, please restart service manually!"
+BOT_TG_UPLOAD_FAIL2="Upload failed, please retry!"
+BOT_TG_NET_UPLOAD_FAIL="Network error, upload failed! Please retry!"
+BOT_TG_FILE_FORMAT_FAIL="File format mismatch, upload failed!"
+BOT_TG_FW_ENABLED="ShellCrash redirect mode "
+BOT_TG_FW_ENABLED_SUFFIX=" enabled!"
+BOT_TG_SWITCH_PURE="Switched to pure mode!"
+BOT_TG_SERVICE_RESTARTED="ShellCrash service restarted!"
+BOT_TG_UNFINISHED="Error: unfinished feature!"
+BOT_TG_SEND_CORE="Please send core file ending with tar.gz/.gz/.upx for ["
+BOT_TG_SEND_CORE_SUFFIX="]"
+BOT_TG_SEND_BAK="Please send backup file in [.tar.gz] format!"
+BOT_TG_SEND_CFG="Please send config file in ["
+BOT_TG_SEND_CFG_SUFFIX="] format, custom config is supported"
+BOT_TG_SWITCH_TO="Switched to "
+BOT_TG_ALREADY="Already in "
+BOT_TG_ALREADY_PURE="Already in pure mode!"
+BOT_TG_SERVICE_RESTARTED_SHORT="🔄 Service restarted"
+BOT_TG_LOG_CONTENT="📄 Logs (task logs filtered):"
+BOT_TG_TASK_WORD="Task"
+BOT_TG_INPUT_SUB="✏ Please enter new subscription URL:"
+BOT_TG_SUB_UPDATED="Subscription update finished:"
diff --git a/scripts/lang/en/check_port.lang b/scripts/lang/en/check_port.lang
new file mode 100644
index 00000000..2e14ca8a
--- /dev/null
+++ b/scripts/lang/en/check_port.lang
@@ -0,0 +1,3 @@
+CHECK_PORT_RANGE_ERR="Invalid input! Please enter a valid value (1-65535)!"
+CHECK_PORT_DUP_ERR="Invalid input! Please do not enter duplicate ports!"
+CHECK_PORT_OCCUPIED_ERR="This port is already occupied by another process. Please enter a different one!"
diff --git a/scripts/lang/en/common.lang b/scripts/lang/en/common.lang
new file mode 100644
index 00000000..9637da78
--- /dev/null
+++ b/scripts/lang/en/common.lang
@@ -0,0 +1,13 @@
+
+COMMON_INPUT="Please enter a number"
+COMMON_INPUT_L="Enter a letter or a number"
+COMMON_INPUT_R="Enable? (1/0) > "
+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!"
diff --git a/scripts/lang/en/ddns.lang b/scripts/lang/en/ddns.lang
new file mode 100644
index 00000000..e97c91b0
--- /dev/null
+++ b/scripts/lang/en/ddns.lang
@@ -0,0 +1,35 @@
+DDNS_WELCOME="Welcome to DDNS!"
+DDNS_ADD_DONE="Service has been added!"
+DDNS_INPUT_DOMAIN="Please enter your domain"
+DDNS_INPUT_USER="Please enter username or email"
+DDNS_INPUT_PASS="Please enter password or token"
+DDNS_INPUT_CHECK_INTERVAL="Please enter check interval (minutes, default 10)"
+DDNS_INPUT_FORCE_INTERVAL="Please enter force update interval (hours, default 24)"
+DDNS_CONFIRM_INFO="Please confirm the following info:"
+DDNS_FIELD_SERVICE="Provider:"
+DDNS_FIELD_DOMAIN="Domain:"
+DDNS_FIELD_USER="Username:"
+DDNS_FIELD_INTERVAL="Check interval:"
+DDNS_CONFIRM_ADD="Confirm add:"
+DDNS_YES="Yes"
+DDNS_REINPUT="No, re-enter"
+DDNS_LIST_NOT_FOUND="DDNS list file not found, trying online update..."
+DDNS_DOWNLOAD_FAILED="Download failed, please retry!"
+DDNS_SELECT_PROVIDER="Please select provider:"
+DDNS_INPUT_ERROR="Invalid input, please retry!"
+DDNS_SELECT_NETMODE="Please select network mode:"
+DDNS_IPV4="IPV4"
+DDNS_IPV6="IPV6"
+DDNS_DISABLE="Disable"
+DDNS_ENABLE="Enable"
+DDNS_UPDATE_NOW="Update now"
+DDNS_EDIT_CURRENT="Edit current service"
+DDNS_CURRENT_SERVICE=" current service"
+DDNS_REMOVE_CURRENT="Remove current service"
+DDNS_VIEW_LOG="View logs"
+DDNS_NOT_SUPPORTED="This feature depends on OpenWrt built-in DDNS service; unsupported on current device."
+DDNS_LIST_HEADER=" List Domain On IP Address"
+DDNS_ADD_SERVICE="Add DDNS service"
+DDNS_EXIT="Exit"
+DDNS_INPUT_INDEX="Please enter index"
+DDNS_INPUT_NUM_ERROR="Please enter a valid number!"
diff --git a/scripts/lang/en/dns.lang b/scripts/lang/en/dns.lang
new file mode 100644
index 00000000..4793b4e5
--- /dev/null
+++ b/scripts/lang/en/dns.lang
@@ -0,0 +1,69 @@
+#===== 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 DIRECT-DNS, others use fake-ip"
+DNS_MODE_ROUTE_DESC="CN domains use DIRECT-DNS, others use PROXY-DNS"
+DNS_MODE_REDIR_DESC="All domains use DIRECT-DNS"
+
+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_RESOLVER="Edit DEFAULT-DNS (must be an IP, used to resolve other DNS servers)"
+DNS_ADV_EDIT_PROXY_SERVER="Edit PROXY-SERVER-DNS (must be an IP, used to resolve proxy hostnames)"
+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"
+DNS_SET_TO="Set to"
+DNS_REMOVE_OK="Removed successfully"
+DNS_REMOVE_FAIL="Remove failed"
+DNS_INPUT_REDIR_PORT="Please input DNS redirect port"
+DNS_INPUT_REDIR_RESET="or input r to reset DNS redirect port"
+DNS_INPUT_REDIR_BACK="or input 0 to go back"
+DNS_INPUT="Please enter"
+DNS_CONFIRM_ADD="Please confirm the address to add: "
+DNS_CONFIRM_OK="Confirm"
+DNS_ADD_OK="Added successfully"
+DNS_ADD_FAIL="Add failed"
+DNS_NOW="Current DNS: "
+DNS_INPUT_NEW="Please input a new DNS address"
+DNS_INPUT_RESET="or input r to reset the DNS address"
diff --git a/scripts/lang/en/fw_filter.lang b/scripts/lang/en/fw_filter.lang
new file mode 100644
index 00000000..119afb1d
--- /dev/null
+++ b/scripts/lang/en/fw_filter.lang
@@ -0,0 +1,91 @@
+FWF_TITLE="Traffic Filter"
+FWF_ITEM_1_PREFIX="1) Filter Common ports: "
+FWF_ITEM_1_SUFFIX="--- filter P2P traffic"
+FWF_ITEM_2_PREFIX="2) Filter LAN devices: "
+FWF_ITEM_2_SUFFIX="--- use black/white list"
+FWF_ITEM_3_PREFIX="3) Filter QUIC protocol: "
+FWF_ITEM_3_SUFFIX="--- improve video"
+FWF_ITEM_4_PREFIX="4) Filter CN_IP list: "
+FWF_ITEM_4_SUFFIX="--- improve performance"
+FWF_ITEM_5="5) Custom transparent routing IPv4 subnet: suitable for vlan and other complex networks"
+FWF_ITEM_6="6) Custom reserved-address IPv4 subnet: for environments that need reserved addresses as targets"
+FWF_BACK="0) $COMMON_BACK"
+FWF_SWITCH_STOP="Switching will stop the service. Continue?"
+FWF_YES="1) Yes"
+FWF_NO_BACK="0) No, return to previous menu"
+FWF_QUIC_OFF="QUIC traffic through the ShellCrash core has been disabled!"
+FWF_QUIC_ON="QUIC protocol traffic disable has been canceled!"
+FWF_CNIP_ON="CN_IP core bypass has been enabled!"
+FWF_CNIP_WARN="Note: this will cause global mode and all CN-related rules to become ineffective!"
+FWF_CNIP_OFF="CN_IP core bypass has been disabled!"
+FWF_NO_IPSET="This device lacks the ipset module or is not using nftables mode, so bypass cannot be enabled!"
+FWF_WHITE_LIST="Whitelist"
+FWF_BLACK_LIST="Blacklist"
+FWF_PASS_WORD="not"
+FWF_COMMON_NOTE="Note:\n"
+FWF_MIX_NOTE="In MIX mode, non-common port traffic from fake-ip sources will not be filtered"
+FWF_ALLOWED_PORTS="Currently allowed ports: "
+FWF_PORT_MENU_1_PREFIX="1) Enable/disable port filtering: \t"
+FWF_PORT_MENU_1_SUFFIX=""
+FWF_PORT_MENU_2="2) Add allowed port"
+FWF_PORT_MENU_3="3) Remove specified allowed port"
+FWF_PORT_MENU_4="4) Reset default allowed ports"
+FWF_PORT_MENU_5="5) Reset to legacy allowed ports"
+FWF_MAX_PORT="Up to 15 allowed ports are supported. Please remove some first!"
+FWF_INPUT_ADD_HINT="Please enter the port number to allow directly"
+FWF_INPUT_ADD_HINT2="(Only one port number at a time. Do not add multiple at once.)"
+FWF_INPUT_REMOVE_HINT="Please enter the port number to remove directly"
+FWF_OR_BACK="Or enter 0 to return to the previous menu"
+FWF_ERR_DUP="Invalid input! Do not add duplicates!"
+FWF_ERR_RANGE="Invalid input! Please enter a valid number (1-65535)!"
+FWF_INPUT_PORT="Please enter> "
+FWF_CUST_HOST_TITLE="Current default transparent routing subnet: "
+FWF_CUST_HOST_TITLE2="Currently added custom subnet(s): "
+FWF_CUST_HOST_MENU_1="1) Remove all custom subnets"
+FWF_CUST_HOST_MENU_2="2) Use custom subnets to override the default subnet"
+FWF_CUST_HOST_HINT="Please enter the number or an additional subnet> "
+FWF_NET_ERR="Please enter a valid subnet address!"
+FWF_RESERVE_NOTE="Note: addresses must be separated by spaces. Incorrect settings may cause network loops or startup errors. Use with caution!"
+FWF_RESERVE_NOW="Current subnet: "
+FWF_RESERVE_INPUT_HINT="Please enter a custom reserved-address IPv4 subnet directly"
+FWF_RESERVE_INPUT_HINT2="Or enter 1 to reset to the default subnet"
+FWF_RESERVE_INPUT_HINT3="Or enter 0 to return to the previous menu"
+FWF_RESERVE_PROMPT="Please enter> "
+FWF_RESERVE_SET="Reserved-address subnet set to: "
+FWF_RESERVE_ERR="Invalid input, please try again!"
+FWF_LAN_NO_DEVICE="Unknown device"
+FWF_MAC_HINT="Manual MAC input only supports the format \033[32mxx:xx:xx:xx:xx:xx\033[0m"
+FWF_MAC_EXISTED="Added MAC addresses:"
+FWF_NONE_MAC="No MAC addresses added yet"
+FWF_MAC_HEADER="No. \033[33mDevice IP Device MAC Device name\033[0m"
+FWF_MAC_NONE="No records"
+FWF_MAC_INPUT_HINT="Please enter the number or a MAC address directly> "
+FWF_MAC_DUP="This device is already added. Do not add it again!"
+FWF_IP_HINT="Manual input only supports \033[32m192.168.1.0/24\033[0m or \033[32m192.168.1.0\033[0m"
+FWF_IP_HINT2="IPv6 addresses are not supported and filtering may fail. MAC filtering is recommended."
+FWF_IP_EXISTED="Added IP addresses (subnets):"
+FWF_NONE_IP="No IP addresses (subnets) added yet"
+FWF_IP_HEADER="\033[33mNo. Device IP Device name\033[32m"
+FWF_IP_INPUT_HINT="Please enter the number or an IP subnet directly> "
+FWF_IP_DUP="This address is already added. Do not add it again!"
+FWF_REMOVE_NONE="There are no devices to remove!"
+FWF_REMOVE_TITLE="Please choose the device to remove:"
+FWF_REMOVE_HEADER=" \033[32mDevice IP \033[36mDevice MAC \033[35mDevice name\033[0m"
+FWF_REMOVE_OK="Corresponding device removed!"
+FWF_FILTER_MENU_TITLE="Add or remove devices here"
+FWF_FILTER_MODE="Current filtering mode: "
+FWF_FILTER_ONLY="Only devices in the list"
+FWF_FILTER_MODE_SUFFIX=" mode"
+FWF_FILTER_PASS="traffic passes through"
+FWF_FILTER_BLACK_DESC="Only the devices in the list bypass the core"
+FWF_FILTER_WHITE_DESC="Only the devices in the list pass through the core"
+FWF_FILTER_EXISTED="Currently filtered devices:"
+FWF_FILTER_HEADER=" \033[36mDevice MAC/IP\033[0m \033[35mDevice name\033[0m"
+FWF_FILTER_SWITCH_PREFIX="1) Switch to "
+FWF_FILTER_SWITCH_SUFFIX=" mode"
+FWF_FILTER_ADD_MAC="2) \033[32mAdd specified device (MAC)\033[0m"
+FWF_FILTER_ADD_IP="3) \033[32mAdd specified device (IP/subnet)\033[0m"
+FWF_FILTER_REMOVE="4) \033[36mRemove specified device\033[0m"
+FWF_FILTER_CLEAR="9) \033[31mClear the entire list\033[0m"
+FWF_SWITCH_OK="Switch completed!"
+FWF_LIST_CLEARED="Device list cleared!"
diff --git a/scripts/lang/en/menu.lang b/scripts/lang/en/menu.lang
new file mode 100644
index 00000000..ece6d34a
--- /dev/null
+++ b/scripts/lang/en/menu.lang
@@ -0,0 +1,89 @@
+# ===== Common Prompts =====
+
+MENU_RESTART_NOTICE="Changes have been detected. Please restart the service!"
+MENU_RESTART_NOW="Restart now"
+MENU_RESTART_LATER="Not now"
+
+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?"
+MENU_YES="Yes"
+MENU_NO="No"
+
+# ===== 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_LOAD_NOW="Load now"
+MENU_LOAD_LATER="Not now"
+
+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:"
diff --git a/scripts/lang/en/override.lang b/scripts/lang/en/override.lang
new file mode 100644
index 00000000..60ea88a2
--- /dev/null
+++ b/scripts/lang/en/override.lang
@@ -0,0 +1,93 @@
+OVR_TITLE="Config Override"
+OVR_MENU_2="2) Manage \033[36mcustom rules\033[0m"
+OVR_MENU_3="3) Manage \033[33mcustom nodes\033[0m"
+OVR_MENU_4="4) Manage \033[36mcustom proxy groups\033[0m"
+OVR_MENU_5="5) \033[32mCustom\033[0m advanced features"
+OVR_MENU_9="9) \033[33mDisable\033[0m config override"
+OVR_BACK="0) Return to previous menu"
+OVR_INPUT_NUM="Please enter the corresponding number> "
+OVR_PROMPT="Please enter> "
+OVR_GROUPS_CHOOSE_TYPE="Please choose the proxy group type:"
+OVR_GROUP_TYPE_CN="Manual Select Auto Select Failover Load Balance"
+OVR_WARN_1="This feature may cause serious problems! Most script functions will be disabled after enabling it!!!"
+OVR_WARN_2_PREFIX="If you are not very familiar with how "
+OVR_WARN_2_SUFFIX=" works, do not enable it!"
+OVR_WARN_3="If any problem occurs after continuing, you must solve it yourself. No questions will be accepted!"
+OVR_WARN_CONFIRM="1) I confirm I can solve any problems myself"
+OVR_CONFIRM_YES="1) Yes"
+OVR_CONFIRM_NO="0) No, return to previous menu"
+OVR_RULES_TITLE="Custom Rules"
+OVR_RULES_MENU_HINT="You can quickly manage custom rules here"
+OVR_RULES_MANUAL="For batch operations, edit manually: \033[36m $YAMLSDIR/rules.yaml\033[0m"
+OVR_RULES_SHARED="singbox and clash share these rules, so switching is seamless!"
+OVR_RULES_WARN="For many rules, use the rule-set feature as much as possible.\n\033[31mToo many rules here may cause startup lag!\033[0m"
+OVR_RULES_ADD="1) Add custom rule"
+OVR_RULES_DEL="2) Remove custom rule"
+OVR_RULES_CLEAR="3) Clear rule list"
+OVR_RULES_BYPASS="4) Configure node bypass:"
+OVR_RULES_NO_RULES="Please add custom rules first!"
+OVR_RULES_CLEAR_CONFIRM="Are you sure you want to clear all custom rules?"
+OVR_RULES_ADD_RULE="Enter the rule text,\nwhich can be a domain, wildcard domain, IP subnet, or other matching rule content"
+OVR_RULES_TYPE="Please choose a rule type:"
+OVR_RULES_GROUP="Please choose a specific rule"
+OVR_RULES_EXIST_WARN="These rules are read from the existing config file. If errors occur after changing the config later, try adding them again."
+OVR_RULES_INPUT_RULE="Please enter the corresponding rule> "
+OVR_RULES_INPUT_NUM="Please enter the corresponding number> "
+OVR_RULES_INPUT_TYPE="Please enter the corresponding number> "
+OVR_RULES_INPUT_SELECT="Please enter the corresponding number> "
+OVR_RULES_DEL_HINT="Enter the corresponding number to remove the matching rule:"
+OVR_RULES_ADD_OK="Added successfully!"
+OVR_RULES_BYPASS_WARN1="This feature will automatically set node domains or IPs from the current config file to direct rules to prevent double traffic!"
+OVR_RULES_BYPASS_WARN2="Make sure the nodes used by downstream devices are the same as those used in ShellCrash, otherwise it will not take effect!"
+OVR_RULES_BYPASS_PROMPT="Enable node bypass?"
+OVR_RULES_BYPASS_CONFIRM="Are you sure you want to clear all custom rules?"
+OVR_GROUPS_TITLE="Custom Clash Proxy Groups"
+OVR_GROUPS_MENU_HINT="You can quickly manage custom proxy groups here"
+OVR_GROUPS_MANUAL="For modifications or batch operations, edit manually: $YAMLSDIR/proxy-groups.yaml"
+OVR_GROUPS_ADD="1) Add custom proxy group"
+OVR_GROUPS_VIEW="2) View custom proxy groups"
+OVR_GROUPS_CLEAR="3) Clear custom proxy groups"
+OVR_GROUPS_WARN1="The proxy group name must match the group specified in the [Custom Rules] or [Custom Nodes] feature!"
+OVR_GROUPS_WARN2="It is recommended to create the proxy group first, then specify it intelligently in [Custom Rules] or [Custom Nodes]"
+OVR_GROUPS_WARN3="To add nodes under the current proxy group, edit $YAMLSDIR/proxy-groups.yaml manually"
+OVR_GROUPS_INPUT_NAME="Please enter the custom proxy group name directly\n(pure numbers are not supported and special characters are not allowed!)"
+OVR_GROUPS_INPUT_NUM="Please enter the corresponding number> "
+OVR_GROUPS_URL="Please enter a test URL"
+OVR_GROUPS_URL_HINT="Or press Enter to use the default URL: https://www.gstatic.com/generate_204"
+OVR_GROUPS_MULTI_HINT="If you want to add to multiple proxy groups, enter multiple numbers separated by spaces"
+OVR_GROUPS_SKIP="0) Skip adding"
+OVR_GROUPS_CLEAR_CONFIRM="Are you sure you want to clear all custom proxy groups?"
+OVR_GROUPS_ADD_OK="Added successfully!"
+OVR_PROXIES_TITLE="Custom Clash Nodes"
+OVR_PROXIES_MENU_HINT="You can quickly manage custom nodes here"
+OVR_PROXIES_MANUAL="For batch operations, edit manually: $YAMLSDIR/proxies.yaml"
+OVR_PROXIES_ADD="1) Add custom node"
+OVR_PROXIES_MANAGE="2) Manage custom nodes"
+OVR_PROXIES_CLEAR="3) Clear custom nodes"
+OVR_PROXIES_BYPASS="4) Configure node bypass:"
+OVR_PROXIES_WARN1="Note\nThe node format must be a single line, without parentheses, and start with \"name:\", for example:"
+OVR_PROXIES_WARN2="For more formats, see: \033[32mhttps://juewuy.github.io/\033[0m"
+OVR_PROXIES_INPUT="Please enter the custom node directly"
+OVR_PROXIES_BLOCK_HASH="Absolutely no [#] character is allowed!"
+OVR_PROXIES_ADD_HINT="Please choose the proxy group to add the node to"
+OVR_PROXIES_MULTI_HINT="If you want to add to multiple proxy groups, enter multiple numbers separated by spaces"
+OVR_PROXIES_GROUP_HINT="To use custom proxy groups, first add them using [Manage custom proxy groups]"
+OVR_PROXIES_EXIST_HINT="Enter the node number to remove the corresponding node"
+OVR_PROXIES_EXIST_TITLE="Currently added custom nodes:"
+OVR_PROXIES_NO_PROXY="Please add custom nodes first!"
+OVR_PROXIES_CLEAR_CONFIRM="Are you sure you want to clear all custom nodes?"
+OVR_PROXIES_BYPASS_WARN1="This feature will automatically set node domains or IPs from the current config file to direct rules to prevent double traffic!"
+OVR_PROXIES_BYPASS_WARN2="Make sure the nodes used by downstream devices are the same as those used in ShellCrash, otherwise it will not take effect!"
+OVR_PROXIES_BYPASS_PROMPT="Enable node bypass:"
+OVR_PROXIES_ADD_OK="Added successfully!"
+OVR_ADV_USER_CREATED1="Custom config file created: $YAMLSDIR/user.yaml!"
+OVR_ADV_USER_CREATED2="Can be used for custom DNS and similar features"
+OVR_ADV_USER_CREATED3="Custom feature file created: $YAMLSDIR/others.yaml!"
+OVR_ADV_USER_CREATED4="Can be used for custom anchors, inbound, proxy-providers, rule-set, sub-rules, script, and similar features"
+OVR_ADV_WIN="On Windows, use \033[33mWinSCP\033[0m to edit it!"
+OVR_ADV_MAC="On macOS, use \033[33mSecureFX\033[0m to edit it!"
+OVR_ADV_LIN="On Linux, you can use \033[33mvim\033[0m to edit it (do not use it on router devices if Chinese text is not displayed)!"
+OVR_SING_TITLE1="Supported modules that can override script settings:"
+OVR_SING_TITLE2="Modules that can be merged with built-in features (but must not conflict):"
+OVR_SING_TITLE3="Place the corresponding JSON files into the \033[33m$JSONSDIR\033[0m directory to load them automatically at startup"
+OVR_SING_TITLE4="Be sure to read the configuration guide before use: \033[32;4m https://juewuy.github.io/nWTjEpkSK \033[0m"
diff --git a/scripts/lang/en/providers.lang b/scripts/lang/en/providers.lang
new file mode 100644
index 00000000..ab2d2f1a
--- /dev/null
+++ b/scripts/lang/en/providers.lang
@@ -0,0 +1,25 @@
+PROVIDERS_MENU_GEN="Generate config including all providers"
+PROVIDERS_MENU_TEMPLATE="Select \033[33mrule template\033[0m"
+PROVIDERS_MENU_CLEAN="\033[33mClean\033[0m providers directory"
+PROVIDERS_INPUT="Please enter a letter or number"
+
+PROVIDERS_EMPTY_HINT="No link or local config file has been added yet. Please add one first!"
+PROVIDERS_TEMPLATE_CURRENT="Current rule template: "
+PROVIDERS_TEMPLATE_SELECT="Please select an online template:"
+PROVIDERS_TEMPLATE_LOCAL="Use \033[36mlocal template\033[0m"
+PROVIDERS_TEMPLATE_PATH="Please enter template path (absolute path)"
+PROVIDERS_TEMPLATE_NOT_FOUND="Invalid input, template file not found!"
+
+PROVIDERS_CLEAN_WARN="This will clear all files under"
+PROVIDERS_CLEAN_WARN_END=""
+PROVIDERS_CLEAN_CONFIRM="Continue?"
+
+PROVIDERS_FETCHING_TEMPLATE="Fetching online template..."
+PROVIDERS_DOWNLOAD_FAILED="Download failed. Please try switching install source!"
+PROVIDERS_GEN_OK="Configuration file generated successfully!"
+PROVIDERS_GEN_OK_SINGBOX="Configuration generated successfully! If startup times out, install the Singbox-srs common database package from Update menu."
+PROVIDERS_GEN_FAILED="Failed to generate configuration file. Please check your input carefully!"
+PROVIDERS_RESTART_ASK="Start/Restart service now?"
+PROVIDERS_YES="Yes"
+PROVIDERS_NO="No"
+PROVIDERS_CRON_SUB_UPDATE="Update subscription"
diff --git a/scripts/lang/en/set_crashdir.lang b/scripts/lang/en/set_crashdir.lang
new file mode 100644
index 00000000..b4229521
--- /dev/null
+++ b/scripts/lang/en/set_crashdir.lang
@@ -0,0 +1,34 @@
+SCD_SELECT_INSTALL_DIR="Please select install directory:"
+SCD_INPUT_NUM="Please enter a number"
+SCD_INPUT_ERROR="Invalid input! Please retry!"
+SCD_XIAOMI_DETECTED="Xiaomi stock firmware detected, select installation location:"
+SCD_CUSTOM_DIR_WARN="Custom directory (not recommended)"
+SCD_EXIT_INSTALL="Exit installation"
+SCD_SELECT_USB_DIR="Please select USB directory:"
+SCD_ASUS_DM_NOT_FOUND="Download Master startup file not found:"
+SCD_CHECK_SETTING="please check your settings!"
+SCD_ASUS_DETECTED="Asus firmware detected, please select installation method"
+SCD_ASUS_INSTALL_DM="Install via USB + Download Master (all firmwares, ARM only)"
+SCD_ASUS_INSTALL_SCRIPT="Install via startup script (some Merlin firmwares only)"
+SCD_ASUS_DM_HINT="Install and enable Download Master in router web UI first, then select external storage directory."
+SCD_ASUS_REINSTALL_HINT="If boot auto-start fails, please reinstall with USB + Download Master."
+SCD_PATH_FORMAT_HINT="Path must start with /. Files under virtual memory (/tmp,/opt,/sys...) will be lost after reboot!"
+SCD_PATH_FREE_SPACE="Available paths free space:"
+SCD_INPUT_CUSTOM_DIR="Please input custom path"
+SCD_PATH_ERROR="Invalid path! Please retry!"
+SCD_INSTALL_SPACE_HINT="Notice: ShellCrash requires at least ~1MB free space"
+SCD_INSTALL_ETC="Install in \033[32m/etc\033[0m (root users)"
+SCD_INSTALL_USR="Install in \033[32m/usr/share\033[0m (Linux systems)"
+SCD_INSTALL_HOME="Install in \033[32mcurrent user dir\033[0m (non-root users)"
+SCD_INSTALL_USB="Install in \033[32mexternal storage\033[0m"
+SCD_INSTALL_MANUAL="Set install directory manually"
+SCD_INSTALL_CANCELED="Installation canceled"
+SCD_NO_WRITE_PREFIX="No write permission on "
+SCD_NO_WRITE_SUFFIX=", please retry!"
+SCD_TARGET_DIR_PREFIX="Target directory "
+SCD_TARGET_DIR_SPACE=" free space: "
+SCD_CONFIRM_INSTALL="Confirm installation?"
+SCD_YES="Yes"
+SCD_NO="No"
+SCD_DIR_FREE=" dir, free: "
+SCD_SOFT_SOLID="(supports soft solidification)"
diff --git a/scripts/lang/en/setboot.lang b/scripts/lang/en/setboot.lang
new file mode 100644
index 00000000..1ca36e37
--- /dev/null
+++ b/scripts/lang/en/setboot.lang
@@ -0,0 +1,52 @@
+SETBOOT_NOT_SET="Not set"
+SETBOOT_SECOND="s"
+SETBOOT_TITLE="Startup Settings"
+SETBOOT_ITEM_AUTO="Autostart:"
+SETBOOT_ITEM_OLD="Conservative mode:"
+SETBOOT_ITEM_OLD_DESC="--- cron based check (every minute)"
+SETBOOT_ITEM_DELAY="Startup delay:"
+SETBOOT_ITEM_DELAY_DESC="--- helps when service is restricted right after boot"
+SETBOOT_ITEM_MINI="Low-flash mode:"
+SETBOOT_ITEM_MINI_DESC="--- for devices with limited flash space"
+SETBOOT_ITEM_MINI_DIR="Low-flash directory:"
+SETBOOT_ITEM_NETCHK="Startup network check:"
+SETBOOT_ITEM_NETCHK_DESC="--- disable to skip network check on startup"
+SETBOOT_VIEW_LOG="View startup logs"
+SETBOOT_AUTO_OFF="ShellCrash autostart disabled!"
+SETBOOT_AUTO_ON="ShellCrash autostart enabled!"
+SETBOOT_CRON_INIT="ShellCrash initialization"
+SETBOOT_OLDMODE_ON="Switched to conservative startup mode!"
+SETBOOT_OLDMODE_OFF="Switched to system daemon startup mode!"
+SETBOOT_MODE_UNSUPPORTED="Current device does not support other startup modes!"
+SETBOOT_DELAY_HINT1="If your device runs normally after boot, no need to configure this."
+SETBOOT_DELAY_HINT2="Recommended between 30~120 seconds, tune according to your device issue."
+SETBOOT_DELAY_INPUT="Please enter startup delay (0~300s)"
+SETBOOT_SET_OK="Set successfully!"
+SETBOOT_DELAY_INVALID="Invalid input or over 300s, please retry!"
+SETBOOT_MINI_NEEDED_NO="Your device has enough space (>20M), no need to enable!"
+SETBOOT_SYSTEMD_WARN="systemd startup is unsupported here, enable conservative mode first!"
+SETBOOT_MINI_ENABLED="Low-flash mode has been enabled!"
+SETBOOT_MINI_DIR_HINT="To change directory, use [Set low-flash directory]."
+SETBOOT_MINI_DISABLE_WARN="Remaining space is below 8M; disabling may break runtime!"
+SETBOOT_MINI_DISABLE_CONFIRM="Confirm disabling this feature?"
+SETBOOT_YES="Yes"
+SETBOOT_NO_BACK="No, return"
+SETBOOT_MINI_DISABLED="Low-flash mode has been disabled!"
+SETBOOT_BINDIR_HINT1="If set to memory, related files will be re-downloaded after each boot."
+SETBOOT_BINDIR_HINT2="Ensure install source is directly reachable, or startup may fail."
+SETBOOT_BINDIR_TMP="Use memory (/tmp)"
+SETBOOT_BINDIR_USB="Select USB directory"
+SETBOOT_BINDIR_CUSTOM="Custom directory"
+SETBOOT_SELECT_INSTALL_DIR="Please select install directory:"
+SETBOOT_SPACE_USED="Used storage:"
+SETBOOT_INPUT_ERROR="Invalid input, please retry!"
+SETBOOT_INPUT_CMD="Please input command/path directly"
+SETBOOT_INPUT_OR_BACK="Or input 0 to return"
+SETBOOT_INPUT="Please enter"
+SETBOOT_NETCHK_HINT1="If your device can run normally after boot, no need to change this."
+SETBOOT_NETCHK_HINT2="When disabled, low-flash or online rules (e.g. rule-set) may fail due to no network."
+SETBOOT_NETCHK_HINT3="When enabled, low-performance/slow-dial devices may timeout and fail startup."
+SETBOOT_NETCHK_OFF_CONFIRM="Network check is \033[33mdisabled\033[0m. Enable it?"
+SETBOOT_NETCHK_ON_CONFIRM="Network check is \033[33menabled\033[0m. Disable it?"
+SETBOOT_TASK_WORD="Task"
+SETBOOT_LOG_NOT_FOUND="Related log not found!"
diff --git a/scripts/lang/en/subconverter.lang b/scripts/lang/en/subconverter.lang
new file mode 100644
index 00000000..7761f82b
--- /dev/null
+++ b/scripts/lang/en/subconverter.lang
@@ -0,0 +1,33 @@
+SUBCONVERTER_MENU_GEN="Generate config including all nodes and subscriptions"
+SUBCONVERTER_MENU_EXCLUDE="Set \033[31mexclude node regex\033[0m"
+SUBCONVERTER_MENU_INCLUDE="Set \033[32minclude node regex\033[0m"
+SUBCONVERTER_MENU_RULE="Select \033[33monline rule template\033[0m"
+SUBCONVERTER_MENU_SERVER="Select Subconverter server"
+SUBCONVERTER_MENU_UA="Custom browser UA"
+
+SUBCONVERTER_INPUT="Please enter"
+SUBCONVERTER_BACK="or enter 0 to return"
+
+SUBCONVERTER_EXCLUDE_HINT1="Nodes matching keywords will be blocked during import!"
+SUBCONVERTER_INCLUDE_HINT1="Only nodes matching keywords will be imported!!!"
+SUBCONVERTER_KEYWORD_SPLIT="Use \033[30;47m | \033[0m to separate multiple keywords"
+SUBCONVERTER_REGEX_HINT="\033[32mRegex is supported\033[0m. Use \033[30;47m + \033[0m instead of spaces"
+SUBCONVERTER_EXCLUDE_INPUT="Enter exclude keyword(s) directly"
+SUBCONVERTER_INCLUDE_INPUT="Enter include keyword(s) directly"
+SUBCONVERTER_EXCLUDE_CLEAR="or enter d to \033[31mclear\033[0m exclude keywords"
+SUBCONVERTER_INCLUDE_CLEAR="or enter d to \033[31mclear\033[0m include keywords"
+
+SUBCONVERTER_RULE_CURRENT="Current rule: "
+SUBCONVERTER_SERVER_HINT="The following third-party servers are collected from the internet. Please evaluate their security by yourself!"
+SUBCONVERTER_SERVER_THANKS="Thanks to the contributors below for their great work!!!"
+SUBCONVERTER_SERVER_CURRENT="Current backend: "
+SUBCONVERTER_SET_OK="Settings saved. Returning to previous menu"
+
+SUBCONVERTER_UA_HINT="Try this if the config file cannot be fetched correctly"
+SUBCONVERTER_UA_CURRENT="Current UA: "
+SUBCONVERTER_UA_AUTO="Use auto UA (default)"
+SUBCONVERTER_UA_NONE="Do not use UA"
+SUBCONVERTER_UA_CUSTOM="Use custom UA"
+SUBCONVERTER_UA_CLEAR="Clear UA"
+SUBCONVERTER_UA_CUSTOM_WARN="Note:\nCustom UA cannot contain spaces or special symbols!"
+SUBCONVERTER_UA_CUSTOM_INPUT="Enter custom UA"
diff --git a/scripts/lang/en/task_cmd.lang b/scripts/lang/en/task_cmd.lang
new file mode 100644
index 00000000..ab93d80c
--- /dev/null
+++ b/scripts/lang/en/task_cmd.lang
@@ -0,0 +1,19 @@
+TASK_CMD_EVERY="every"
+TASK_CMD_HOURLY="hourly"
+TASK_CMD_MIN="minute"
+TASK_CMD_CORE_SKIP="Task [Auto update core] skipped - no new version detected"
+TASK_CMD_CORE_DONE="Task [Auto update core] download complete, restarting service"
+TASK_CMD_CORE_DL_FAIL="Task [Auto update core] failed - download error"
+TASK_CMD_CORE_VERIFY_FAIL="Task [Auto update core] failed - core verification error"
+TASK_CMD_SCRIPT_SKIP="Task [Auto update script] skipped - no new version detected"
+TASK_CMD_SCRIPT_UNZIP_FAIL="Task [Auto update script] failed - extract error"
+TASK_CMD_DB_SKIP_PREFIX="Task [Auto update database] skipped - no new version for "
+TASK_CMD_DB_SKIP_SUFFIX=""
+TASK_CMD_DB_DL_FAIL_PREFIX="Task [Auto update database] failed downloading ["
+TASK_CMD_DB_DL_FAIL_SUFFIX="]"
+TASK_CMD_DB_OK_PREFIX="Task [Auto update database] updated ["
+TASK_CMD_DB_OK_SUFFIX="] successfully"
+TASK_CMD_RES_OK="success"
+TASK_CMD_RES_FAIL="failed"
+TASK_CMD_EXEC_PREFIX="Task ["
+TASK_CMD_EXEC_MID="] result: "
diff --git a/scripts/lang/en/uninstall.lang b/scripts/lang/en/uninstall.lang
new file mode 100644
index 00000000..3d2f1ede
--- /dev/null
+++ b/scripts/lang/en/uninstall.lang
@@ -0,0 +1,13 @@
+UNINSTALL_WARN="Warning: this action is irreversible!"
+UNINSTALL_CONFIRM="Are you sure you want to uninstall ShellCrash?"
+UNINSTALL_YES="Yes"
+UNINSTALL_NO="No"
+UNINSTALL_KEEP_CONFIRM="Keep script configs and subscription files?"
+UNINSTALL_ENV_ERROR="Environment variable configuration is incorrect. Please remove the installation directory manually!"
+UNINSTALL_DONE="ShellCrash related files have been removed. Goodbye!"
+UNINSTALL_CLOSE_HINT="Please close the current terminal window manually to reset environment variables!"
+UNINSTALL_CANCELED="Operation canceled!"
+UNINSTALL_CRON_CLASH="clash service"
+UNINSTALL_CRON_SUB="subscription link"
+UNINSTALL_CRON_INIT="ShellCrash initialization"
+UNINSTALL_SSH_MARK="Enable SSH access from WAN"
diff --git a/scripts/lang/en/userguide.lang b/scripts/lang/en/userguide.lang
new file mode 100644
index 00000000..26569b02
--- /dev/null
+++ b/scripts/lang/en/userguide.lang
@@ -0,0 +1,17 @@
+
+UG_WELCOME="Welcome to User Guide!"
+UG_CHOOSE_ENV="Please select your usage environment:"
+UG_TIP_CONFIG="(You can still change various settings later)"
+UG_OPTION_1="Router: LAN transparent proxy"
+UG_OPTION_2="Linux device: local proxy only"
+UG_OPTION_3="Restore previous backup settings"
+UG_RESTORE_OK="Script settings have been restored! Please restart the script!"
+UG_IP_FORWARD_WARN="Your device has not enabled IP forwarding, LAN devices will not connect properly. Enable now?"
+UG_ENABLE_LOW_MEM="Your installation directory is less than 10MB, enable low-flash mode?"
+UG_IMPORT_CONFIG="Import configuration file? (Last step before running)"
+UG_CONFIG_TIP="You must have a configuration file to run the service!"
+UG_CONFIG_RES="Importing now? "
+UG_FINAL_TIP="Great! Now just start the service to enjoy!"
+
+UG_IMPORT_NOW="Import now"
+UG_IMPORT_LATER="Not now"
diff --git a/scripts/libs/check_autostart.sh b/scripts/libs/check_autostart.sh
index c9b8bff2..f07c80ca 100644
--- a/scripts/libs/check_autostart.sh
+++ b/scripts/libs/check_autostart.sh
@@ -1,17 +1,17 @@
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
- [ ! -f "$CRASHDIR"/.dis_startup ] && 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
+ 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
+ [ ! -f "$CRASHDIR"/.dis_startup ] && 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
}
diff --git a/scripts/libs/check_cpucore.sh b/scripts/libs/check_cpucore.sh
index cae95fee..2dd40cb0 100644
--- a/scripts/libs/check_cpucore.sh
+++ b/scripts/libs/check_cpucore.sh
@@ -1,14 +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
+ 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
}
diff --git a/scripts/libs/check_dir_avail.sh b/scripts/libs/check_dir_avail.sh
index b2a68f7b..a08acac8 100644
--- a/scripts/libs/check_dir_avail.sh
+++ b/scripts/libs/check_dir_avail.sh
@@ -1,5 +1,5 @@
#检查目录剩余空间——$1:目标路径 $2:-h参数
dir_avail() {
- df -h >/dev/null 2>&1 && h="$2"
+ df -h >/dev/null 2>&1 && h="$2"
df -P $h "${1:-.}" 2>/dev/null | awk 'NR==2 {print $4}'
}
diff --git a/scripts/libs/check_target.sh b/scripts/libs/check_target.sh
index b8efc811..81a45e8e 100644
--- a/scripts/libs/check_target.sh
+++ b/scripts/libs/check_target.sh
@@ -1,8 +1,8 @@
if echo "$crashcore" | grep -q 'singbox'; then
- target=singbox
- format=json
+ target=singbox
+ format=json
else
- target=clash
- format=yaml
+ target=clash
+ format=yaml
fi
core_config="$CRASHDIR/${format}s/config.$format"
diff --git a/scripts/libs/compare.sh b/scripts/libs/compare.sh
index c0f3a684..913781b6 100644
--- a/scripts/libs/compare.sh
+++ b/scripts/libs/compare.sh
@@ -3,7 +3,7 @@ compare() { #对比文件
return 1
elif ckcmd cmp; then
cmp -s "$1" "$2"
- return $?
+ return $?
else
[ "$(cat "$1")" = "$(cat "$2")" ] && return 0 || return 1
fi
diff --git a/scripts/libs/core_tools.sh b/scripts/libs/core_tools.sh
index 4bd1decb..a0ea7e7f 100644
--- a/scripts/libs/core_tools.sh
+++ b/scripts/libs/core_tools.sh
@@ -2,88 +2,110 @@
[ -n "$(find --help 2>&1 | grep -o size)" ] && find_para=' -size +2000' #find命令兼容
+#根据环境权衡决定是否把裸二进制存于$BINDIR(rom)——省RAM,前提是rom装得下
+#$1=裸二进制字节数。仅当$TMPDIR在内存(tmpfs)时裸存才省RAM;
+#再按$BINDIR文件系统估算裸二进制落盘体积(透明压缩fs约2:1),需留有余量($raw_margin,默认8M)
+store_raw_worth_it(){
+ case "$(df -T "$TMPDIR" 2>/dev/null | awk 'END{print $2}')" in tmpfs|ramfs) ;; *) return 1 ;; esac
+ rom_free=$(df -k "$BINDIR" 2>/dev/null | awk 'END{print $4}') #KB
+ [ -z "$rom_free" ] && return 1
+ case "$(df -T "$BINDIR" 2>/dev/null | awk 'END{print $2}')" in
+ squashfs|ubifs|overlay|overlayfs) est=$(( ${1:-0}/1024/2 )) ;; #透明压缩,约2:1
+ *) est=$(( ${1:-0}/1024 )) ;; #无压缩,全量
+ esac
+ [ $(( rom_free - est )) -gt "${raw_margin:-8192}" ] && return 0 || return 1
+}
+
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"
+ 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 '.raw$' ;then
+ ln -sf "$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
- [ -n "$(find "$CRASHDIR"/CrashCore.* $find_para 2>/dev/null)" ] && [ "$CRASHDIR" != "$BINDIR" ] &&
- mv -f "$CRASHDIR"/CrashCore.* "$BINDIR"/
- core_dir=$(find "$BINDIR"/CrashCore.* $find_para 2>/dev/null | head -n 1)
- [ -n "$core_dir" ] && core_unzip "$core_dir" CrashCore
- fi
+ if [ ! -f "$TMPDIR"/CrashCore ];then
+ [ -n "$(find "$CRASHDIR"/CrashCore.* $find_para 2>/dev/null)" ] && [ "$CRASHDIR" != "$BINDIR" ] &&
+ mv -f "$CRASHDIR"/CrashCore.* "$BINDIR"/
+ core_dir=$(find "$BINDIR"/CrashCore.* $find_para 2>/dev/null | head -n 1)
+ [ -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
- if [ "$zip_type" = 'upx' ];then
- rm -f "$1" "$TMPDIR"/core_new
- ln -sf "$TMPDIR/CrashCore.upx" "$TMPDIR/CrashCore"
- else
- mv -f "$TMPDIR/core_new" "$TMPDIR/CrashCore"
- fi
- 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
+ [ -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 "$BINDIR"/CrashCore.raw
+ if [ "$zip_type" = 'upx' ];then
+ mv -f "$1" "$BINDIR/CrashCore.upx"
+ rm -f "$TMPDIR"/core_new
+ ln -sf "$BINDIR/CrashCore.upx" "$TMPDIR/CrashCore"
+ elif store_raw_worth_it "$(wc -c < "$TMPDIR/core_new")" ;then
+ rm -f "$1"
+ mv -f "$TMPDIR/core_new" "$BINDIR/CrashCore.raw"
+ ln -sf "$BINDIR/CrashCore.raw" "$TMPDIR/CrashCore"
+ elif [ -z "$zip_type" ];then
+ gzip -c "$TMPDIR/core_new" > "$BINDIR/CrashCore.gz"
+ mv -f "$TMPDIR/core_new" "$TMPDIR/CrashCore"
+ else
+ mv -f "$1" "$BINDIR/CrashCore.$zip_type"
+ mv -f "$TMPDIR/core_new" "$TMPDIR/CrashCore"
+ fi
+ 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
- case "$custcorelink" in
- *.tar.gz) zip_type="tar.gz" ;;
- *.gz) zip_type="gz" ;;
- *.upx) zip_type="upx" ;;
- esac
- [ -n "$zip_type" ] && webget "$TMPDIR/Coretmp.$zip_type" "$custcorelink"
- fi
- #校验内核
- if [ "$?" = 0 ];then
- core_check "$TMPDIR/Coretmp.$zip_type"
- else
- rm -f "$TMPDIR/Coretmp.$zip_type"
- return 1
- fi
+ . "$CRASHDIR"/libs/web_get_bin.sh
+ . "$CRASHDIR"/libs/check_target.sh
+ if [ -z "$custcorelink" ];then
+ [ -z "$zip_type" ] && zip_type='tar.gz'
+ #若环境适合裸存(见store_raw_worth_it,按典型核心~45M估算),避免下载upx,改取tar.gz的裸二进制
+ [ "$zip_type" = 'upx' ] && store_raw_worth_it 47185920 && zip_type='tar.gz'
+ get_bin "$TMPDIR/Coretmp.$zip_type" "bin/$crashcore/${target}-linux-${cpucore}.$zip_type"
+ else
+ case "$custcorelink" in
+ *.tar.gz) zip_type="tar.gz" ;;
+ *.gz) zip_type="gz" ;;
+ *.upx) zip_type="upx" ;;
+ esac
+ [ -n "$zip_type" ] && webget "$TMPDIR/Coretmp.$zip_type" "$custcorelink"
+ fi
+ #校验内核
+ if [ "$?" = 0 ];then
+ core_check "$TMPDIR/Coretmp.$zip_type"
+ else
+ rm -f "$TMPDIR/Coretmp.$zip_type"
+ return 1
+ fi
}
diff --git a/scripts/libs/gen_base64.sh b/scripts/libs/gen_base64.sh
index a3b36a87..591c3e3d 100644
--- a/scripts/libs/gen_base64.sh
+++ b/scripts/libs/gen_base64.sh
@@ -1,26 +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
+ 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
+ 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
}
\ No newline at end of file
diff --git a/scripts/libs/get_config.sh b/scripts/libs/get_config.sh
index ba9b6b08..af3305d4 100644
--- a/scripts/libs/get_config.sh
+++ b/scripts/libs/get_config.sh
@@ -1,5 +1,6 @@
# 检查配置文件
+[ -z "$TASKCFGDIR" ] && TASKCFGDIR="$CRASHDIR"/configs/task
[ -f "$CRASHDIR"/configs/ShellCrash.cfg ] || . "$CRASHDIR"/init.sh >/dev/null 2>&1
. "$CRASHDIR"/configs/command.env >/dev/null 2>&1
. "$CRASHDIR"/configs/ShellCrash.cfg
@@ -15,8 +16,9 @@ routing_mark=$((fwmark + 2))
[ -z "$table" ] && table=100
[ -z "$dns_nameserver" ] && {
- dns_nameserver='223.5.5.5, 1.2.4.8'
- netstat -ntlup 2>/dev/null | grep -q '127.0.0.1:53' && dns_nameserver='127.0.0.1'
+ dns_nameserver='223.5.5.5, 1.2.4.8'
+ netstat -ntlup 2>/dev/null | grep -q '127.0.0.1:53' && 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"
+[ -z "$dns_proxy_server" ] && dns_proxy_server="$dns_resolver"
diff --git a/scripts/libs/get_ecsip.sh b/scripts/libs/get_ecsip.sh
index 21cec0fa..ba8e10a2 100644
--- a/scripts/libs/get_ecsip.sh
+++ b/scripts/libs/get_ecsip.sh
@@ -5,11 +5,12 @@ get_ecs_address() {
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
+ . "$CRASHDIR"/libs/web_get_lite.sh
+ #轮询公网IP,提取并校验为合法IPv4才采用,否则继续尝试下一个
+ for web in http://ddns.oray.com/checkip http://members.3322.org/dyndns/getip http://ipinfo.io/ip; do
+ ip=$(web_get_lite "$web" 0 | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | tail -1)
+ [ -n "$ip" ] && return
+ done
}
get_ecs_address
[ -n "$ip" ] && ecs_address="${ip%.*}.0/24"
diff --git a/scripts/libs/i18n.sh b/scripts/libs/i18n.sh
new file mode 100644
index 00000000..01ec63eb
--- /dev/null
+++ b/scripts/libs/i18n.sh
@@ -0,0 +1,8 @@
+
+load_lang() {
+ i18n=$(cat "$CRASHDIR"/configs/i18n.cfg 2>/dev/null)
+ [ -z "$i18n" ] && i18n=chs
+
+ i18n_file="$CRASHDIR/lang/$i18n/$1.lang"
+ [ -s "$i18n_file" ] && . "$i18n_file"
+}
\ No newline at end of file
diff --git a/scripts/libs/logger.sh b/scripts/libs/logger.sh
index cb832b6e..3e3989e7 100644
--- a/scripts/libs/logger.sh
+++ b/scripts/libs/logger.sh
@@ -1,14 +1,18 @@
+
+[ -n "$__IS_LIB_LOGGER" ] && return
+__IS_LIB_LOGGER=1
+
#日志工具
. "$CRASHDIR"/libs/web_json.sh
#$1日志内容$2显示颜色$3是否推送$4是否覆盖上一条
logger() {
- TMPDIR=/tmp/ShellCrash
+ 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"
- [ "$4" = on ] && sed -i "/$1/d" "$TMPDIR"/ShellCrash.log
+ [ "$4" = on ] && sed -i "/$1/d" "$TMPDIR"/ShellCrash.log
echo "$log_text" >>"$TMPDIR"/ShellCrash.log
[ "$(wc -l "$TMPDIR"/ShellCrash.log | awk '{print $1}')" -gt 199 ] && sed -i '1,20d' "$TMPDIR"/ShellCrash.log
- #推送远程日志
+ #推送远程日志
[ "$3" != off ] && {
[ -n "$device_name" ] && log_text="$log_text($device_name)"
[ -n "$push_TG" ] && {
@@ -23,7 +27,8 @@ logger() {
web_json_post "$url" "$content" &
}
[ -n "$push_Deer" ] && {
- url="https://api2.pushdeer.com/message/push"
+ url="${push_Deer_url%/}"
+ url="${url:-https://api2.pushdeer.com}/message/push"
content="{\"pushkey\":\"${push_Deer}\",\"text\":\"$log_text\"}"
web_json_post "$url" "$content" &
}
@@ -46,6 +51,6 @@ logger() {
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" &
- }
+ }
} &
}
diff --git a/scripts/libs/meta_listeners.sh b/scripts/libs/meta_listeners.sh
index c338a769..cf9d5b67 100644
--- a/scripts/libs/meta_listeners.sh
+++ b/scripts/libs/meta_listeners.sh
@@ -3,7 +3,7 @@
#meta内核vmess入站生成
[ "$vms_service" = ON ] && {
- cat >>"$TMPDIR"/listeners.yaml <>"$TMPDIR"/listeners.yaml <>"$TMPDIR"/listeners.yaml <>"$TMPDIR"/listeners.yaml </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 <"$TMPDIR"/jsons/tailscale.json </dev/null && {
- [ -n "$wg_ipv6" ] && wg_ipv6_add=", \"$wg_ipv6\""
- cat >"$TMPDIR"/jsons/wireguard.json <"$TMPDIR"/jsons/wireguard.json <"$TMPDIR"/jsons/vmess-in.json <"$TMPDIR"/jsons/vmess-in.json <"$TMPDIR"/jsons/ss-in.json <"$TMPDIR"/jsons/ss-in.json <>"$configpath"
+ sed -i "/^${1}=.*/d" "$configpath"
+ printf '%s=%s\n' "$1" "$2" >>"$configpath"
}
\ No newline at end of file
diff --git a/scripts/libs/set_cron.sh b/scripts/libs/set_cron.sh
index fddf57ad..a586d1d2 100644
--- a/scripts/libs/set_cron.sh
+++ b/scripts/libs/set_cron.sh
@@ -4,36 +4,38 @@ crondir="$(crond -h 2>&1 | grep -oE 'Default:.*' | awk -F ":" '{print $2}'| tr -
[ ! -w "$crondir" ] && crondir="/var/spool/cron/crontabs"
[ ! -w "$crondir" ] && crondir="/var/spool/cron"
[ -z "$USER" ] && USER=$(whoami 2>/dev/null)
+[ -z "$TASKCFGDIR" ] && TASKCFGDIR="$CRASHDIR"/configs/task
tmpcron=/tmp/cron_tmp
touch "$tmpcron"
cronadd() { #定时任务工具
- if crontab -h 2>&1 | grep -q '\-l'; then
+ if crontab -h 2>&1 | grep -q '\-l'; then
crontab "$1"
- elif [ -f "$crondir/$USER" ];then
- cat "$1" >"$crondir"/"$USER" && cru a REFRESH "0 0 1 1 * /bin/true" 2>/dev/null
- else
- echo "找不到可用的crond或者crontab应用!No available crond or crontab application can be found!"
- fi
+ elif [ -w "$crondir" ];then
+ cat "$1" >"$crondir"/"$USER" && cru a REFRESH "0 0 1 1 * /bin/true" 2>/dev/null
+ else
+ echo "找不到可用的crond或者crontab应用!No available crond or crontab application can be found!"
+ fi
}
cronload() { #定时任务工具
- if crontab -h 2>&1 | grep -q '\-l'; then
+ if crontab -h 2>&1 | grep -q '\-l'; then
crontab -l
- elif [ -f "$crondir/$USER" ];then
- cat "$crondir"/"$USER" 2>/dev/null
- else
- return 1
- fi
+ elif [ -f "$crondir/$USER" ];then
+ cat "$crondir"/"$USER" 2>/dev/null
+ else
+ return 1
+ fi
}
cronset() { #定时任务设置
# 参数1代表要移除的关键字,参数2代表要添加的任务语句
cronload | grep -v '^$' | grep -vF "$1" >"$tmpcron"
[ -n "$2" ] && echo "$2" >>"$tmpcron"
- cronadd "$tmpcron"
- #华硕/Padavan固件存档在本地,其他则删除
- if [ -d /jffs ] || [ -d /etc/storage/ShellCrash ];then
- mv -f "$tmpcron" "$CRASHDIR"/task/cron
- else
- rm -f "$tmpcron"
- fi
+ cronadd "$tmpcron"
+ #华硕/Padavan固件存档在本地,其他则删除
+ if [ -d /jffs ] || [ -d /etc/storage/ShellCrash ];then
+ mkdir -p "$TASKCFGDIR"
+ mv -f "$tmpcron" "$TASKCFGDIR"/cron
+ else
+ rm -f "$tmpcron"
+ fi
}
diff --git a/scripts/libs/set_profile.sh b/scripts/libs/set_profile.sh
index b16966ed..d8ea7ba7 100644
--- a/scripts/libs/set_profile.sh
+++ b/scripts/libs/set_profile.sh
@@ -5,5 +5,5 @@ set_profile() {
echo "alias ${my_alias}=\"$shtype $CRASHDIR/menu.sh\"" >>"$1" #设置快捷命令环境变量
sed -i '/export CRASHDIR=*/'d "$1"
echo "export CRASHDIR=\"$CRASHDIR\"" >>"$1" #设置路径环境变量
- . "$1" >/dev/null 2>&1 || true
+ . "$1" >/dev/null 2>&1 || true
}
\ No newline at end of file
diff --git a/scripts/libs/set_proxy.sh b/scripts/libs/set_proxy.sh
index c5e0c8ff..7a5f9abd 100644
--- a/scripts/libs/set_proxy.sh
+++ b/scripts/libs/set_proxy.sh
@@ -1,9 +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"
- }
+ [ -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"
+ }
}
\ No newline at end of file
diff --git a/scripts/libs/start_wait.sh b/scripts/libs/start_wait.sh
index ffbee612..2daa7201 100644
--- a/scripts/libs/start_wait.sh
+++ b/scripts/libs/start_wait.sh
@@ -1,10 +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))
+ 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
diff --git a/scripts/libs/web_get.sh b/scripts/libs/web_get.sh
index c05f7f4b..1e6a6c67 100644
--- a/scripts/libs/web_get.sh
+++ b/scripts/libs/web_get.sh
@@ -1,57 +1,77 @@
. "$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=''
- if [ "$5" = "skipceroff" ] || [ "$skip_cert" = OFF ];then
- certificate=''
- else
- certificate='--no-check-certificate'
- fi
- 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'
- if [ "$5" = "skipceroff" ] || [ "$skip_cert" = OFF ];then
- certificate=''
- else
- certificate='-k'
- fi
- 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
-}
\ No newline at end of file
+ if pidof CrashCore >/dev/null; then
+ setproxy #设置临时代理,【$1】代表下载目录,【$2】代表在线地址
+ 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=''
+ if [ "$5" = "skipceroff" ] || [ "$skip_cert" = OFF ];then
+ certificate=''
+ else
+ certificate='--no-check-certificate'
+ fi
+ 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
+ if [ "$3" = "echooff" ];then
+ progress='-s'
+ elif echo "$url" | grep -q 'jsdelivr.net';then
+ progress='-#'
+ . "$CRASHDIR"/libs/web_get_curlbar.sh && curl_fsize
+ else
+ progress='-#'
+ fi
+ [ "$4" = "rediroff" ] && redirect='' || redirect='-L'
+ if [ "$5" = "skipceroff" ] || [ "$skip_cert" = OFF ];then
+ certificate=''
+ else
+ certificate='-k'
+ fi
+ # curl 特殊版本兼容
+ auth_arg=""
+ if curl --version | grep -q '^curl 8.' && ckcmd base64; then
+ auth_b64=$(printf '%s' "$authentication" | base64)
+ [ -n "$auth_b64" ] && auth_arg="--proxy-header Proxy-Authorization:Basic $auth_b64"
+ fi
+ if [ -n "$fsize_raw" ] && [ "$fsize_raw" -gt 204800 ]; then
+ result=$(execute_curl "$1" "$url" "$fsize_raw" "$agent $auth_arg $redirect $certificate")
+ else
+ result=$(curl $agent $auth_arg -w '%{http_code}' --connect-timeout 3 $progress $redirect $certificate -o "$1" "$url")
+ fi
+
+ [ "$result" = "200" ] && return 0 #成功则退出否则重试
+ export https_proxy=""
+ export http_proxy=""
+
+ if [ -n "$fsize_raw" ] && [ "$fsize_raw" -gt 204800 ]; then
+ result=$(execute_curl "$1" "$2" "$fsize_raw" "$agent $redirect $certificate")
+ else
+ result=$(curl $agent -w '%{http_code}' --connect-timeout 5 $progress $redirect $certificate -o "$1" "$2")
+ fi
+ [ "$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
+}
diff --git a/scripts/libs/web_get_bin.sh b/scripts/libs/web_get_bin.sh
index c319519a..d434b670 100644
--- a/scripts/libs/web_get_bin.sh
+++ b/scripts/libs/web_get_bin.sh
@@ -3,13 +3,13 @@
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
+ [ -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特殊处理
+ bin_url="$(grep "$url_id" "$CRASHDIR"/configs/servers_chs.list | awk '{print $3}')@$rt/$2" #jsdelivr特殊处理
else
- bin_url="$(grep "$url_id" "$CRASHDIR"/configs/servers.list | awk '{print $3}')/$rt/$2"
+ bin_url="$(grep "$url_id" "$CRASHDIR"/configs/servers_chs.list | awk '{print $3}')/$rt/$2"
fi
else
bin_url="$update_url/$2"
diff --git a/scripts/libs/web_get_curlbar.sh b/scripts/libs/web_get_curlbar.sh
new file mode 100644
index 00000000..b6c29b61
--- /dev/null
+++ b/scripts/libs/web_get_curlbar.sh
@@ -0,0 +1,47 @@
+
+bar_max=42 #进度条长度
+
+curl_fsize(){ # 获取文件大小
+ fsize_raw=0
+ header=$(curl -sIL --connect-timeout 2 "$url")
+ # 代理容错
+ [ -z "$header" ] && { export https_proxy=""; export http_proxy=""; header=$(curl -sIL --connect-timeout 2 "$url"); }
+ # 提取大小 (优先 Content-Length,其次 ETag)
+ fsize_raw=$(echo "$header" | grep -i 'Content-Length' | tail -n 1 | awk '{print $2}' | tr -d '\r' | awk '{print int($1)}')
+ if [ -z "$fsize_raw" ] || [ "$fsize_raw" -eq 0 ]; then
+ etag=$(echo "$header" | grep -i 'etag' | tail -n 1 | cut -d '"' -f2 | cut -d '-' -f1)
+ [ -n "$etag" ] && fsize_raw=$(printf "%d" 0x$etag 2>/dev/null)
+ fi
+}
+
+execute_curl(){ # 手搓curl进度条
+ local path="$1" target_url="$2" total_size="$3" extra_args="$4"
+ rm -f /tmp/webget_res
+ # 后台静默下载,状态码写入临时文件
+ curl $extra_args -s -L -w '%{http_code}' "$target_url" -o "$path" > /tmp/webget_res &
+ local pid=$!
+
+ # 循环监控
+ while kill -0 $pid 2>/dev/null; do
+ if [ -f "$path" ]; then
+ local curr=$(wc -c < "$path")
+ local pct=$(awk -v c=$curr -v t=$total_size 'BEGIN {p=(c*100/t); if(p>100)p=100; printf "%.1f", p}')
+ local num=$(awk -v p=$pct -v w=$bar_max 'BEGIN {printf "%d", p*w/100}')
+ local bar=$(printf "%${num}s" | tr ' ' '#'); local spc_n=$((bar_max - num))
+ local spc=""; [ "$spc_n" -gt 0 ] && spc=$(printf "%${spc_n}s")
+ local size=$(( fsize_raw * 100 / 1048576 ))
+ local fs="$((size / 100)).$((size % 100)) MB"
+ printf "\r\033[2K%s%s %6s%%(%s)" "$bar" "$spc" "$pct" "$fs" >&2
+ fi
+ usleep 200000 2>/dev/null || sleep 1
+ done
+
+ local code=$(cat /tmp/webget_res 2>/dev/null)
+ if [ "$code" = "200" ] || [ "$code" = "206" ]; then
+ local full=$(printf "%${bar_max}s" | tr ' ' '#')
+ printf "\r\033[2K%s 100.0%%(%s)\n" "$full" "$fs" >&2
+ else
+ printf "\r\033[2K" >&2; [ -f "$path" ] && rm -f "$path"
+ fi
+ echo "$code"
+}
\ No newline at end of file
diff --git a/scripts/libs/web_get_lite.sh b/scripts/libs/web_get_lite.sh
index cf485b18..2eead479 100644
--- a/scripts/libs/web_get_lite.sh
+++ b/scripts/libs/web_get_lite.sh
@@ -1,10 +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
+ [ -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
}
diff --git a/scripts/libs/web_json.sh b/scripts/libs/web_json.sh
index 3c76260b..22b659e6 100644
--- a/scripts/libs/web_json.sh
+++ b/scripts/libs/web_json.sh
@@ -1,10 +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
+ 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
}
diff --git a/scripts/libs/web_restore.sh b/scripts/libs/web_restore.sh
index e0368803..9907059d 100644
--- a/scripts/libs/web_restore.sh
+++ b/scripts/libs/web_restore.sh
@@ -9,12 +9,12 @@ put_save() { #推送面板选择
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
+ 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
}
diff --git a/scripts/libs/web_save.sh b/scripts/libs/web_save.sh
index e7a16f3f..e734a6c0 100644
--- a/scripts/libs/web_save.sh
+++ b/scripts/libs/web_save.sh
@@ -1,32 +1,42 @@
+get_save() { #获取面板信息并内部处理所有异常
+ local response exit_code
+ if curl --version >/dev/null 2>&1; then
+ response=$(curl -sf -H "Authorization: Bearer ${secret}" -H "Content-Type:application/json" "$1" 2>&1)
+ exit_code=$?
+ [ $exit_code -eq 0 ] && [ -n "$response" ] && [ "$response" != "{}" ] && {
+ echo "$response"
+ return 0
+ }
+ return 1
+ elif [ -n "$(wget --help 2>&1 | grep '\-\-method')" ]; then
+ response=$(wget -q --header="Authorization: Bearer ${secret}" --header="Content-Type:application/json" -O - "$1" 2>&1)
+ exit_code=$?
+ [ $exit_code -eq 0 ] && [ -n "$response" ] && [ "$response" != "{}" ] && {
+ echo "$response"
+ return 0
+ }
+ return 1
+ fi
+ return 1
+}
-#
-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
+ #使用get_save获取面板节点设置,失败自动退出
+ response=$(get_save "http://127.0.0.1:${db_port}/proxies") || return 1
+
+ echo "$response" | sed 's/{}//g' | sed 's/:{/\
+/g' | grep -aE '"Selector"' >"$TMPDIR"/web_proxies
+
+ >"$TMPDIR"/web_save
+ [ -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 -f "$TMPDIR"/web_proxies
+ . "$CRASHDIR"/libs/compare.sh && compare "$TMPDIR"/web_save "$CRASHDIR"/configs/web_save
+ [ "$?" = 0 ] && rm -f "$TMPDIR"/web_save || mv -f "$TMPDIR"/web_save "$CRASHDIR"/configs/web_save
}
diff --git a/scripts/menu.sh b/scripts/menu.sh
index 81ad278f..c902871c 100644
--- a/scripts/menu.sh
+++ b/scripts/menu.sh
@@ -5,54 +5,103 @@ CRASHDIR=$(
cd $(dirname $0)
pwd
)
+
CFG_PATH="$CRASHDIR"/configs/ShellCrash.cfg
-#加载执行目录,失败则初始化
+
+# 加载执行目录,失败则初始化
. "$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"
-#通用工具
+# 通用工具
. "$CRASHDIR"/libs/set_config.sh
. "$CRASHDIR"/libs/check_cmd.sh
. "$CRASHDIR"/libs/check_autostart.sh
+. "$CRASHDIR"/libs/i18n.sh
+. "$CRASHDIR"/menus/common.sh
. "$CRASHDIR"/menus/1_start.sh
. "$CRASHDIR"/menus/running_status.sh
-errornum() {
- echo "-----------------------------------------------"
- echo -e "\033[31m请输入正确的字母或数字!\033[0m"
-}
+
+# 加载Tui界面
+[ -z "$tui_type" ] && tui_type='tui_layout'
+[ "$1" = '-l' ] && tui_type='tui_lite'
+. "$CRASHDIR"/menus/"$tui_type".sh
+
+# 加载语言
+load_lang common
+load_lang menu
+
checkrestart() {
- echo "-----------------------------------------------"
- echo -e "\033[32m检测到已变更的内容,请重启服务!\033[0m"
- echo "-----------------------------------------------"
- read -p "是否现在重启服务?(1/0) > " res
- [ "$res" = 1 ] && start_service
+ comp_box "\033[32m$MENU_RESTART_NOTICE\033[0m"
+ btm_box "1) $MENU_RESTART_NOW" \
+ "0) $MENU_RESTART_LATER"
+ read -r -p "$COMMON_INPUT> " res
+ if [ "$res" = 1 ]; then
+ start_service
+ fi
}
-checkport() { #检查端口冲突
- for portx in $dns_port $mix_port $redir_port $((redir_port + 1)) $db_port; do
- if [ -n "$(netstat -ntul 2>&1 | grep ':$portx ')" ]; then
- echo "-----------------------------------------------"
- echo -e "检测到端口【$portx】被以下进程占用!内核可能无法正常启动!\033[33m"
- echo $(netstat -ntul | grep :$portx | head -n 1)
- echo -e "\033[0m-----------------------------------------------"
- echo -e "\033[36m请修改默认端口配置!\033[0m"
+# 检查端口冲突
+checkport() {
+ . "$CRASHDIR"/menus/check_port.sh
+
+ while true; do
+ local conflict_found=0
+ local conflict_port=""
+ local conflict_info=""
+
+ conflict_info=$(check_port_with_info "$mix_port")
+ if [ $? -ne 0 ]; then
+ conflict_found=1
+ conflict_port="$mix_port"
+ fi
+
+ if [ "$conflict_found" -eq 0 ]; then
+ conflict_info=$(check_port_with_info "$redir_port")
+ [ $? -ne 0 ] && conflict_found=1 && conflict_port="$redir_port"
+ fi
+
+ if [ "$conflict_found" -eq 0 ]; then
+ conflict_info=$(check_port_with_info "$((redir_port + 1))")
+ [ $? -ne 0 ] && conflict_found=1 && conflict_port="$((redir_port + 1))"
+ fi
+
+ if [ "$conflict_found" -eq 0 ]; then
+ conflict_info=$(check_port_with_info "$dns_port")
+ [ $? -ne 0 ] && conflict_found=1 && conflict_port="$dns_port"
+ fi
+
+ if [ "$conflict_found" -eq 0 ]; then
+ conflict_info=$(check_port_with_info "$db_port" tcp)
+ [ $? -ne 0 ] && conflict_found=1 && conflict_port="$db_port"
+ fi
+
+ if [ "$conflict_found" -eq 1 ]; then
+ comp_box "【$conflict_port】:$MENU_PORT_CONFLICT_TITLE" \
+ "\033[0m$conflict_info\033[0m" \
+ "\033[36m$MENU_PORT_CONFLICT_HINT\033[0m"
+
. "$CRASHDIR"/menus/2_settings.sh && set_adv_config
. "$CRASHDIR"/libs/get_config.sh
- checkport
+ else
+ break
fi
done
}
-ckstatus() { #脚本启动前检查
+
+# 脚本启动前检查
+ckstatus() {
versionsh=$(cat "$CRASHDIR"/version)
[ -n "$versionsh" ] && versionsh_l=$versionsh
- [ -z "$redir_mod" ] && redir_mod=纯净模式
- #获取本机host地址
+ [ -z "$redir_mod" ] && redir_mod="$MENU_PURE_MOD"
+
+ # 获取本机host地址
[ -z "$host" ] && host=$(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" ] && host=$(ip a 2>&1 | grep -w 'inet' | grep 'global' | grep 'lan' | grep -E ' 1(92|0|72)\.' | sed 's/.*inet.//g' | sed 's/\/[0-9][0-9].*$//g' | head -n 1)
[ -z "$host" ] && host=$(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)
- [ -z "$host" ] && host='设备IP地址'
- #dashboard目录位置
+ [ -z "$host" ] && host='$MENU_IP_DF'
+
+ # dashboard目录位置
if [ -f /www/clash/index.html ]; then
dbdir=/www/clash
hostdir=/clash
@@ -60,242 +109,250 @@ ckstatus() { #脚本启动前检查
dbdir="$CRASHDIR"/ui
hostdir=":$db_port/ui"
fi
- #开机自启检测
+
if check_autostart; then
- auto="\033[32m已设置开机启动!\033[0m"
- auto1="\033[36m禁用\033[0mShellCrash开机启动"
+ auto="\033[32m$MENU_AUTOSTART_ON\033[0m"
else
- auto="\033[31m未设置开机启动!\033[0m"
- auto1="\033[36m允许\033[0mShellCrash开机启动"
+ auto="\033[31m$MENU_AUTOSTART_OFF\033[0m"
fi
- #获取运行状态
+
PID=$(pidof CrashCore | awk '{print $NF}')
if [ -n "$PID" ]; then
- run="\033[32m正在运行($redir_mod)\033[0m"
+ run="\033[32m$MENU_RUN_ON($redir_mod$MENU_MOD)\033[0m"
running_status
elif [ "$firewall_area" = 5 ] && [ -n "$(ip route list table 100)" ]; then
- run="\033[32m已设置($redir_mod)\033[0m"
+ run="\033[32m$MENU_RUN_SET($redir_mod$MENU_MOD)\033[0m"
else
- run="\033[31m没有运行($redir_mod)\033[0m"
- #检测系统端口占用
+ run="\033[31m$MENU_RUN_OFF($redir_mod$MENU_MOD)\033[0m"
+ # 检测系统端口占用
checkport
fi
corename=$(echo $crashcore | sed 's/singboxr/SingBoxR/' | sed 's/singbox/SingBox/' | sed 's/clash/Clash/' | sed 's/meta/Mihomo/')
- [ "$firewall_area" = 5 ] && corename='转发'
- [ -f "$TMPDIR"/debug.log -o -f "$CRASHDIR"/debug.log -a -n "$PID" ] && auto="\033[33m并处于debug状态!\033[0m"
- #输出状态
- echo "-----------------------------------------------"
- echo -e "\033[30;46m欢迎使用ShellCrash!\033[0m 版本:$versionsh_l"
- echo -e "$corename服务$run,$auto"
- if [ -n "$PID" ]; then
- echo -e "当前内存占用:\033[44m"$VmRSS"\033[0m,已运行:\033[46;30m"$day"\033[44;37m"$time"\033[0m"
- fi
- echo -e "TG频道:\033[36;4mhttps://t.me/ShellClash\033[0m"
- echo "-----------------------------------------------"
- #检查新手引导
+ # [ "$firewall_area" = 5 ] && corename='转发'
+ [ -f "$TMPDIR"/debug.log -o -f "$CRASHDIR"/debug.log -a -n "$PID" ] && auto="\033[33m$MENU_AUTOSTART_DEBUG\033[0m"
+
+ # 检查新手引导
if [ -z "$userguide" ]; then
userguide=1
+ . "$CRASHDIR"/menus/userguide.sh && userguide
setconfig userguide 1
- . "$CRASHDIR"/menus/8_tools.sh && userguide
- . "$CRASHDIR"/configs/ShellCrash.cfg
+ . "$CRASHDIR"/configs/ShellCrash.cfg
fi
- #检查执行权限
+
+ # 检查执行权限
[ ! -x "$CRASHDIR"/start.sh ] && chmod +x "$CRASHDIR"/start.sh
- #检查/tmp内核文件
+
+ # 检查/tmp内核文件
for file in $(ls /tmp | grep -v [/$] | grep -v ' ' | grep -Ev ".*(zip|7z|tar)$" | grep -iE 'CrashCore|^clash$|^clash-linux.*|^mihomo.*|^sing.*box'); do
- echo -e "发现可用的内核文件: \033[36m/tmp/$file\033[0m "
- read -p "是否加载(会停止当前服务)?(1/0) > " res
+ local tmp_file="/tmp/$file"
+ comp_box "$MENU_TMP_CORE_FOUND \033[36m$tmp_file\033[0m" \
+ "$MENU_TMP_CORE_ASK"
+ btm_box "1) $MENU_LOAD_NOW" \
+ "0) $MENU_LOAD_LATER"
+ read -r -p "$COMMON_INPUT> " res
[ "$res" = 1 ] && {
- zip_type=$(echo "$file" | grep -oE 'tar.gz$|upx$|gz$')
- . "$CRASHDIR"/menus/9_upgrade.sh && setcoretype
- . "$CRASHDIR"/libs/core_tools.sh && core_check "/tmp/$file"
- if [ "$?" = 0 ]; then
- echo -e "\033[32m内核加载完成!\033[0m "
- switch_core
+ zip_type=$(echo "$tmp_file" | grep -oE 'tar.gz$|upx$|gz$')
+ . "$CRASHDIR"/menus/9_upgrade.sh && setcoretype
+ . "$CRASHDIR"/libs/core_tools.sh && core_check "$tmp_file"
+ if [ "$?" = 0 ] && [ -n "$crashcore" ]; then
+ msg_alert "\033[32m$MENU_CORE_LOADED_OK\033[0m"
+ switch_core
else
- echo -e "\033[33m检测到不可用的内核文件!可能是文件受损或CPU架构不匹配!\033[0m"
- rm -rf /tmp/"$file"
- echo -e "\033[33m内核文件已移除,请认真检查后重新上传!\033[0m"
+ rm -rf "$tmp_file"
+ msg_alert "\033[33m$MENU_CORE_LOADED_BAD\033[0m" \
+ "\033[33m$MENU_CORE_REMOVED\033[0m"
fi
- sleep 1
}
- echo "-----------------------------------------------"
done
- #检查/tmp配置文件
+
+ # 检查/tmp配置文件
for file in $(ls /tmp | grep -v [/$] | grep -v ' ' | grep -iE 'config.yaml$|config.yml$|config.json$'); do
- tmp_file=/tmp/$file
- echo -e "发现内核配置文件: \033[36m/tmp/$file\033[0m "
- read -p "是否加载为$crashcore的配置文件?(1/0) > " res
+ local tmp_file="/tmp/$file"
+ comp_box "$MENU_TMP_CFG_FOUND\033[36m$tmp_file\033[0m" \
+ "$MENU_TMP_CFG_ASK"
+ btm_box "1) $MENU_LOAD_NOW" \
+ "0) $MENU_LOAD_LATER"
+ read -p "$COMMON_INPUT> " res
[ "$res" = 1 ] && {
- if [ -n "$(echo /tmp/$file | grep -iE '.json$')" ]; then
- mv -f /tmp/$file "$CRASHDIR"/jsons/config.json
+ if [ -n "$(echo $tmp_file | grep -iE '.json$')" ]; then
+ mv -f "$tmp_file" "$CRASHDIR"/jsons/config.json
else
- mv -f /tmp/$file "$CRASHDIR"/yamls/config.yaml
+ mv -f "$tmp_file" "$CRASHDIR"/yamls/config.yaml
fi
- echo -e "\033[32m配置文件加载完成!\033[0m "
- sleep 1
+ msg_alert "\033[32m$MENU_CFG_LOADED_OK\033[0m "
}
done
- #检查禁用配置覆写
+
+ # 检查禁用配置覆写
[ "$disoverride" = "1" ] && {
- echo -e "\033[33m你已经禁用了配置文件覆写功能,这会导致大量脚本功能无法使用!\033[0m "
- read -p "是否取消禁用?(1/0) > " res
+ comp_box "\033[33m$MENU_OVERRIDE_WARN\033[0m" \
+ "$MENU_OVERRIDE_ASK"
+ btm_box "1) $MENU_YES" \
+ "0) $MENU_NO"
+ read -p "$COMMON_INPUT> " res
[ "$res" = 1 ] && unset disoverride && setconfig disoverride
- echo "-----------------------------------------------"
}
+
+ top_box "\033[30;43m$MENU_WELCOME\033[0m\t\t Ver: $versionsh_l" \
+ "$MENU_TG_CHANNEL\033[36;4mhttps://t.me/ShellClash\033[0m"
+ separator_line "-"
+ content_line "$corename$run\t $auto"
+ if [ -n "$PID" ]; then
+ content_line "$MENU_MEM_USED\033[44m$VmRSS\033[0m\t $MENU_RUNNING_TIME\033[46;30m$day\033[44;37m$time\033[0m"
+ fi
+ separator_line "="
}
-#主菜单
main_menu() {
- #############################
- ckstatus
- #############################
- echo -e " 1 \033[32m启动/重启服务\033[0m"
- echo -e " 2 \033[36m功能设置\033[0m"
- echo -e " 3 \033[31m停止服务\033[0m"
- echo -e " 4 \033[33m启动设置\033[0m"
- echo -e " 5 设置\033[32m自动任务\033[0m"
- echo -e " 6 管理\033[36m配置文件\033[0m"
- echo -e " 7 \033[33m访问与控制\033[0m"
- echo -e " 8 \033[0m工具与优化\033[0m"
- echo -e " 9 \033[32m更新与支持\033[0m"
- echo "-----------------------------------------------"
- echo -e " 0 \033[0m退出脚本\033[0m"
- read -p "请输入对应数字 > " num
+ while true; do
+ ckstatus
- case "$num" in
- 0)
- exit
- ;;
- 1)
- start_service
- exit
- ;;
- 2)
- checkcfg=$(cat "$CFG_PATH")
- . "$CRASHDIR"/menus/2_settings.sh && settings
- if [ -n "$PID" ]; then
- checkcfg_new=$(cat "$CFG_PATH")
- [ "$checkcfg" != "$checkcfg_new" ] && checkrestart
- fi
- main_menu
- ;;
- 3)
- [ "$bot_tg_service" = ON ] && . "$CRASHDIR"/menus/bot_tg_service.sh && bot_tg_stop
- "$CRASHDIR"/start.sh stop
- sleep 1
- echo "-----------------------------------------------"
- echo -e "\033[31m$corename服务已停止!\033[0m"
- main_menu
- ;;
- 4)
- . "$CRASHDIR"/menus/4_setboot.sh && setboot
- main_menu
- ;;
- 5)
- . "$CRASHDIR"/menus/5_task.sh && task_menu
- main_menu
- ;;
- 6)
- . "$CRASHDIR"/menus/6_core_config.sh && set_core_config
- main_menu
- ;;
- 7)
- GT_CFG_PATH="$CRASHDIR"/configs/gateway.cfg
- touch "$GT_CFG_PATH"
- checkcfg=$(cat "$CFG_PATH" "$GT_CFG_PATH")
- . "$CRASHDIR"/menus/7_gateway.sh && gateway
- if [ -n "$PID" ]; then
- checkcfg_new=$(cat "$CFG_PATH" "$GT_CFG_PATH")
- [ "$checkcfg" != "$checkcfg_new" ] && checkrestart
- fi
- main_menu
- ;;
- 8)
- . "$CRASHDIR"/menus/8_tools.sh && tools
- main_menu
- ;;
- 9)
- checkcfg=$(cat "$CFG_PATH")
- . "$CRASHDIR"/menus/9_upgrade.sh && upgrade
- if [ -n "$PID" ]; then
- checkcfg_new=$(cat "$CFG_PATH")
- [ "$checkcfg" != "$checkcfg_new" ] && checkrestart
- fi
- main_menu
- ;;
- *)
- errornum
- exit
- ;;
- esac
+ btm_box "1) \033[32m$MENU_MAIN_1\033[0m" \
+ "2) \033[36m$MENU_MAIN_2\033[0m" \
+ "3) \033[31m$MENU_MAIN_3\033[0m" \
+ "4) \033[33m$MENU_MAIN_4\033[0m" \
+ "5) \033[32m$MENU_MAIN_5\033[0m" \
+ "6) \033[36m$MENU_MAIN_6\033[0m" \
+ "7) \033[33m$MENU_MAIN_7\033[0m" \
+ "8) $MENU_MAIN_8" \
+ "9) \033[32m$MENU_MAIN_9\033[0m" \
+ "" \
+ "0) $MENU_MAIN_0"
+ read -r -p "$MENU_MAIN_PROMPT" num
+
+ case "$num" in
+ "" | 0)
+ line_break
+ exit 0
+ ;;
+ 1)
+ start_service
+ line_break
+ exit
+ ;;
+ 2)
+ checkcfg=$(cat "$CFG_PATH")
+ . "$CRASHDIR"/menus/2_settings.sh && settings
+ if [ -n "$PID" ]; then
+ checkcfg_new=$(cat "$CFG_PATH")
+ [ "$checkcfg" != "$checkcfg_new" ] && checkrestart
+ fi
+ ;;
+ 3)
+ [ "$bot_tg_service" = ON ] && . "$CRASHDIR"/menus/bot_tg_service.sh && bot_tg_stop
+ "$CRASHDIR"/start.sh stop
+ sleep 1
+ msg_alert "\033[31m$corename$MENU_SERVICE_STOPPED\033[0m"
+ ;;
+ 4)
+ . "$CRASHDIR"/menus/4_setboot.sh && setboot
+ ;;
+ 5)
+ . "$CRASHDIR"/menus/5_task.sh && task_menu
+ ;;
+ 6)
+ . "$CRASHDIR"/menus/6_core_config.sh && set_core_config
+ ;;
+ 7)
+ GT_CFG_PATH="$CRASHDIR"/configs/gateway.cfg
+ touch "$GT_CFG_PATH"
+ checkcfg=$(cat "$CFG_PATH" "$GT_CFG_PATH")
+ . "$CRASHDIR"/menus/7_gateway.sh && gateway
+ if [ -n "$PID" ]; then
+ checkcfg_new=$(cat "$CFG_PATH" "$GT_CFG_PATH")
+ [ "$checkcfg" != "$checkcfg_new" ] && checkrestart
+ fi
+ ;;
+ 8)
+ . "$CRASHDIR"/menus/8_tools.sh && tools
+ ;;
+ 9)
+ checkcfg=$(cat "$CFG_PATH")
+ . "$CRASHDIR"/menus/9_upgrade.sh && upgrade
+ if [ -n "$PID" ]; then
+ checkcfg_new=$(cat "$CFG_PATH")
+ [ "$checkcfg" != "$checkcfg_new" ] && checkrestart
+ fi
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
}
case "$1" in
- "")
- main_menu
+"")
+ main_menu
;;
- -t)
- shtype=sh
- ckcmd bash && shtype=bash
- $shtype -x "$CRASHDIR"/menu.sh
+-l)
+ main_menu
;;
- -s)
- "$CRASHDIR"/start.sh "$2" "$3" "$4" "$5" "$6"
+-t)
+ shtype=sh
+ [ -n "$(ls -l /bin/sh | grep -o dash)" ] && shtype=bash
+ "$shtype" -x "$CRASHDIR"/menu.sh -l
;;
- -i)
- . "$CRASHDIR"/init.sh 2>/dev/null
+-s)
+ "$CRASHDIR"/start.sh "$2" "$3" "$4" "$5" "$6"
;;
- -st)
- shtype=sh
- ckcmd bash && shtype=bash
- "$shtype" -x "$CRASHDIR"/starts/bfstart.sh
- . "$CRASHDIR"/starts/start_legacy.sh
- start_legacy "$COMMAND" 'shellcrash'
- "$shtype" -x "$CRASHDIR"/starts/afstart.sh
- "$CRASHDIR"/start.sh stop
+-i)
+ . "$CRASHDIR"/init.sh 2>/dev/null
;;
- -d)
- shtype=sh && [ -n "$(ls -l /bin/sh | grep -o dash)" ] && shtype=bash
- echo -e "正在测试运行!如发现错误请截图后前往\033[32;4mt.me/ShellClash\033[0m咨询"
- $shtype "$CRASHDIR"/start.sh debug >/dev/null 2>"$TMPDIR"/debug_sh_bug.log
- $shtype -x "$CRASHDIR"/start.sh debug >/dev/null 2>"$TMPDIR"/debug_sh.log
- echo -----------------------------------------
- cat "$TMPDIR"/debug_sh_bug.log | grep 'start\.sh' >"$TMPDIR"/sh_bug
- if [ -s "$TMPDIR"/sh_bug ]; then
- while read line; do
- echo -e "发现错误:\033[33;4m$line\033[0m"
- grep -A 1 -B 3 "$line" "$TMPDIR"/debug_sh.log
- echo -----------------------------------------
- done <"$TMPDIR"/sh_bug
- rm -rf "$TMPDIR"/sh_bug
- echo -e "\033[32m测试完成!\033[0m完整执行记录请查看:\033[36m$TMPDIR/debug_sh.log\033[0m"
- else
- echo -e "\033[32m测试完成!没有发现问题,请重新启动服务~\033[0m"
- rm -rf "$TMPDIR"/debug_sh.log
- fi
- "$CRASHDIR"/start.sh stop
+-st)
+ shtype=sh
+ ckcmd bash && shtype=bash
+ "$shtype" -x "$CRASHDIR"/starts/bfstart.sh
+ . "$CRASHDIR"/starts/start_legacy.sh
+ start_legacy "$COMMAND" 'shellcrash'
+ "$shtype" -x "$CRASHDIR"/starts/afstart.sh
+ "$CRASHDIR"/start.sh stop
;;
- -u)
- . "$CRASHDIR"/menus/uninstall.sh && uninstall
+-d)
+ shtype=sh && [ -n "$(ls -l /bin/sh | grep -o dash)" ] && shtype=bash
+ comp_box "$MENU_TEST_RUNNING_1" \
+ "$MENU_TEST_RUNNING_2\033[36;4mhttps://t.me/ShellClash\033[0m"
+ "$shtype" "$CRASHDIR"/start.sh debug >/dev/null 2>"$TMPDIR"/debug_sh_bug.log
+ "$shtype" -x "$CRASHDIR"/start.sh debug >/dev/null 2>"$TMPDIR"/debug_sh.log
+ cat "$TMPDIR"/debug_sh_bug.log | grep 'start\.sh' >"$TMPDIR"/sh_bug
+ if [ -s "$TMPDIR"/sh_bug ]; then
+ line_break
+ echo "==========================================================="
+ while read line; do
+ echo -e "$MENU_ERROR_FOUND\033[33;4m$line\033[0m"
+ grep -A 1 -B 3 "$line" "$TMPDIR"/debug_sh.log
+ echo
+ done <"$TMPDIR"/sh_bug
+ echo "==========================================================="
+ rm -rf "$TMPDIR"/sh_bug
+ comp_box "\033[32m$MENU_TEST_DONE_FAIL\033[0m" \
+ "$MENU_TEST_LOG_HINT\033[36m$TMPDIR/debug_sh.log\033[0m"
+ else
+ rm -rf "$TMPDIR"/debug_sh.log
+ comp_box "\033[32m$MENU_TEST_DONE_OK\033[0m"
+ line_break
+ fi
+ "$CRASHDIR"/start.sh stop
;;
- *)
- echo -----------------------------------------
- echo "欢迎使用ShellCrash"
- echo -----------------------------------------
- echo " -t 测试模式"
- echo " -h 帮助列表"
- echo " -u 卸载脚本"
- echo " -i 初始化脚本"
- echo " -d 测试运行"
- echo -----------------------------------------
- echo " crash -s start 启动服务"
- echo " crash -s stop 停止服务"
- echo " $CRASHDIR/start.sh init 开机初始化"
- echo -----------------------------------------
- echo "在线求助:t.me/ShellClash"
- echo "官方博客:juewuy.github.io"
- echo "发布页面:github.com/juewuy/ShellCrash"
- echo -----------------------------------------
+-u)
+ . "$CRASHDIR"/menus/uninstall.sh && uninstall
+ ;;
+*)
+ comp_box "$MENU_WELCOME"
+ content_line "-t $MENU_CLI_TEST"
+ content_line "-h $MENU_CLI_HELP"
+ content_line "-u $MENU_CLI_UNINSTALL"
+ content_line "-i $MENU_CLI_INIT"
+ content_line "-d $MENU_CLI_DEBUG"
+ separator_line "-"
+ content_line "crash -s start $MENU_CLI_START"
+ content_line "crash -s stop $MENU_CLI_STOP"
+ content_line "$CRASHDIR/start.sh init $MENU_CLI_BOOT_INIT"
+ separator_line "-"
+ content_line "$MENU_HELP_ONLINE\033[36mhttps://t.me/ShellClash\033[0m"
+ content_line "$MENU_HELP_BLOG\033[36mhttps://juewuy.github.io\033[0m"
+ content_line "$MENU_HELP_GITHUB\033[36mhttps://github.com/juewuy/ShellCrash\033[0m"
+ separator_line "="
+ line_break
;;
esac
diff --git a/scripts/menus/1_start.sh b/scripts/menus/1_start.sh
index 29b13ca3..95161332 100644
--- a/scripts/menus/1_start.sh
+++ b/scripts/menus/1_start.sh
@@ -3,49 +3,65 @@
[ -n "$__IS_MODULE_1_START_LOADED" ] && return
__IS_MODULE_1_START_LOADED=1
+load_lang 1_start
-#启动相关
+# ===== 启动完成提示 =====
startover() {
- echo -ne " \r"
- echo -e "\033[32m服务已启动!\033[0m"
- echo -e "请使用 \033[4;36mhttp://$host$hostdir\033[0m 管理内置规则"
- if [ "$redir_mod" = "纯净模式" ]; then
- echo "-----------------------------------------------"
- echo -e "其他设备可以使用PAC配置连接:\033[4;32mhttp://$host:$db_port/ui/pac\033[0m"
- echo -e "或者使用HTTP/SOCK5方式连接:IP{\033[36m$host\033[0m}端口{\033[36m$mix_port\033[0m}"
+ top_box "\033[32m$START_SERVICE_OK\033[0m" \
+ "$START_WEB_HINT \033[4;36mhttp://$host$hostdir\033[0m"
+ 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
+ core_config="$CRASHDIR/jsons/config.json"
else
- core_config="$CRASHDIR"/yamls/config.yaml
+ core_config="$CRASHDIR/yamls/config.yaml"
fi
- echo "-----------------------------------------------"
- if [ ! -s $core_config -a -s "$CRASHDIR"/configs/providers.cfg ]; then
- echo -e "\033[33m没有找到${crashcore}配置文件,尝试生成providers配置文件!\033[0m"
- [ "$crashcore" = singboxr ] && coretype=singbox
- [ "$crashcore" = meta -o "$crashcore" = clashpre ] && coretype=clash
- . "$CRASHDIR"/menus/6_core_config.sh && gen_${coretype}_providers
- elif [ -s $core_config -o -n "$Url" -o -n "$Https" ]; then
- "$CRASHDIR"/start.sh start
- #设置循环检测以判定服务启动是否成功
- . "$CRASHDIR"/libs/start_wait.sh
- [ -n "$test" -o -n "$(pidof CrashCore)" ] && {
- #启动TG机器人
- [ "$bot_tg_service" = ON ] && . "$CRASHDIR"/menus/bot_tg_service.sh && bot_tg_start
- startover
- }
+
+ 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
+
+ comp_box "\033[33m$START_NO_CORE_CFG_TRY_GEN\033[0m"
+ 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
- echo -e "\033[31m没有找到${crashcore}配置文件,请先导入配置文件!\033[0m"
- . "$CRASHDIR"/menus/6_core_config.sh && set_core_config
+ comp_box "\033[31m$START_NO_CORE_CFG_IMPORT_FIRST\033[0m"
+ . "$CRASHDIR/menus/6_core_config.sh" && set_core_config
fi
}
+
+# ===== 启动服务入口 =====
start_service() {
if [ "$firewall_area" = 5 ]; then
- "$CRASHDIR"/start.sh start
- echo -e "\033[32m已完成防火墙设置!\033[0m"
+ "$CRASHDIR/start.sh" start
+ comp_box "\033[32m$START_FIREWALL_DONE\033[0m"
+ line_break
else
start_core
fi
diff --git a/scripts/menus/2_settings.sh b/scripts/menus/2_settings.sh
index 50988b02..27e510ba 100644
--- a/scripts/menus/2_settings.sh
+++ b/scripts/menus/2_settings.sh
@@ -4,932 +4,688 @@
[ -n "$__IS_MODULE_2_SETTINGS_LOADED" ] && return
__IS_MODULE_2_SETTINGS_LOADED=1
-settings() { #功能设置
- #获取设置默认显示
- [ -z "$skip_cert" ] && skip_cert=ON
- [ -z "$sniffer" ] && {
- sniffer=OFF
- echo "$crashcore" | grep -q 'singbox' && sniffer=ON
- }
- [ -z "$dns_mod" ] && dns_mod='redir_host'
- #
- echo "-----------------------------------------------"
- echo -e "\033[30;47m欢迎使用功能设置菜单:\033[0m"
- echo "-----------------------------------------------"
- echo -e " 1 路由模式设置: \033[36m$redir_mod\033[0m"
- echo -e " 2 DNS设置: \033[36m$dns_mod\033[0m"
- echo -e " 3 透明路由\033[32m流量过滤\033[0m"
- [ "$disoverride" != "1" ] && {
- echo -e " 4 跳过证书验证: \033[36m$skip_cert\033[0m"
- echo -e " 5 启用域名嗅探: \033[36m$sniffer\033[0m"
- echo -e " 6 自定义\033[32m端口及秘钥\033[0m"
- }
- echo -e " 8 ipv6设置: \033[36m$ipv6_redir\033[0m"
- echo "-----------------------------------------------"
- echo -e " 9 \033[31m重置/备份/还原\033[0m脚本设置"
- echo -e " 0 返回上级菜单 \033[0m"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0)
- ;;
- 1)
- if [ "$USER" != "root" -a "$USER" != "admin" ]; then
- echo "-----------------------------------------------"
- read -p "非root用户可能无法正确配置其他模式!依然尝试吗?(1/0) > " res
- [ "$res" = 1 ] && set_redir_mod
- else
- set_redir_mod
- fi
- sleep 1
- settings
- ;;
- 2)
- . "$CRASHDIR"/menus/dns.sh && set_dns_mod
- sleep 1
- settings
- ;;
- 3)
- set_fw_filter
- sleep 1
- settings
- ;;
- 4)
- echo "-----------------------------------------------"
- if [ "$skip_cert" = "OFF" ] >/dev/null 2>&1; then
- echo -e "\033[33m已设为开启跳过本地证书验证!!\033[0m"
- skip_cert=ON
- else
- echo -e "\033[33m已设为禁止跳过本地证书验证!!\033[0m"
- skip_cert=OFF
- fi
- setconfig skip_cert $skip_cert
- settings
- ;;
- 5)
- echo "-----------------------------------------------"
- if [ "$sniffer" = "OFF" ]; then
- if [ "$crashcore" = "clash" ]; then
- rm -rf ${TMPDIR}/CrashCore
- rm -rf "$CRASHDIR"/CrashCore
- rm -rf "$CRASHDIR"/CrashCore.tar.gz
- crashcore=meta
- setconfig crashcore $crashcore
- echo "已将ShellCrash内核切换为Meta内核!域名嗅探依赖Meta或者高版本clashpre内核!"
- fi
- sniffer=ON
- elif [ "$crashcore" = "clashpre" -a "$dns_mod" = "redir_host" ]; then
- echo -e "\033[31m使用clashpre内核且开启redir-host模式时无法关闭!\033[0m"
- else
- sniffer=OFF
- fi
- setconfig sniffer $sniffer
- settings
- ;;
- 6)
- 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
- set_adv_config
- fi
- else
- set_adv_config
- fi
- settings
- ;;
- 8)
- set_ipv6
- settings
- ;;
- 9)
- echo "-----------------------------------------------"
- echo -e " 1 备份脚本设置"
- echo -e " 2 还原脚本设置"
- echo -e " 3 重置脚本设置"
- echo -e " 0 返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- if [ -z "$num" ]; then
- errornum
- elif [ "$num" = 0 ]; then
- i=
- elif [ "$num" = 1 ]; then
- cp -f "$CFG_PATH" "$CFG_PATH".bak
- echo -e "\033[32m脚本设置已备份!\033[0m"
- elif [ "$num" = 2 ]; then
- if [ -f "$CFG_PATH.bak" ]; then
- mv -f "$CFG_PATH" "$CFG_PATH".bak2
- mv -f "$CFG_PATH".bak "$CFG_PATH"
- mv -f "$CFG_PATH".bak2 "$CFG_PATH".bak
- echo -e "\033[32m脚本设置已还原!(被覆盖的配置已备份!)\033[0m"
- else
- echo -e "\033[31m找不到备份文件,请先备份脚本设置!\033[0m"
- fi
- elif [ "$num" = 3 ]; then
- mv -f "$CFG_PATH" "$CFG_PATH".bak
- . "$CRASHDIR"/init.sh >/dev/null
- echo -e "\033[32m脚本设置已重置!(旧文件已备份!)\033[0m"
- fi
- echo -e "\033[33m请重新启动脚本!\033[0m"
- exit 0
- ;;
- *)
- errornum
- ;;
- esac
-}
+load_lang 2_settings
-set_redir_mod() { #路由模式设置
- set_redir_config() {
- setconfig redir_mod $redir_mod
- setconfig dns_mod $dns_mod
- echo "-----------------------------------------------"
- echo -e "\033[36m已设为 $redir_mod !!\033[0m"
- }
- [ -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
- [ -z "$redir_mod" ] && [ "$USER" = "root" -o "$USER" = "admin" ] && redir_mod='Redir模式'
- [ -z "$redir_mod" ] && redir_mod='纯净模式'
- firewall_area_dsc=$(echo "仅局域网 仅本机 局域网+本机 纯净模式 主-旁转发($bypass_host)" | cut -d' ' -f$firewall_area)
- echo "-----------------------------------------------"
- echo -e "当前路由模式为:\033[47;30m$redir_mod\033[0m;ShellCrash核心为:\033[47;30m $crashcore \033[0m"
- echo -e "\033[33m切换模式后需要手动重启服务以生效!\033[0m"
- echo "-----------------------------------------------"
- [ $firewall_area -le 3 ] && {
- echo -e " 1 \033[32mRedir模式\033[0m: Redir转发TCP,不转发UDP"
- echo -e " 2 \033[36m混合模式\033[0m: Redir转发TCP,Tun转发UDP"
- echo -e " 3 \033[32mTproxy模式\033[0m: Tproxy转发TCP&UDP"
- echo -e " 4 \033[33mTun模式\033[0m: Tun转发TCP&UDP(占用高不推荐)"
- echo "-----------------------------------------------"
- }
- [ "$firewall_area" = 5 ] && {
- echo -e " 5 \033[32mTCP旁路转发\033[0m: 仅转发TCP流量至旁路由"
- echo -e " 6 \033[36mT&U旁路转发\033[0m: 转发TCP&UDP流量至旁路由"
- echo "-----------------------------------------------"
- }
- echo -e " 7 设置路由劫持范围: \033[47;30m$firewall_area_dsc\033[0m"
- echo -e " 8 容器/虚拟机劫持: \033[47;30m$vm_redir\033[0m"
- echo -e " 9 切换防火墙应用: \033[47;30m$firewall_mod\033[0m"
- echo "-----------------------------------------------"
- echo " 0 返回上级菜单"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0) ;;
- 1)
- redir_mod=Redir模式
- set_redir_config
- set_redir_mod
- ;;
- 2)
- if [ -n "$sup_tun" ]; then
- redir_mod=混合模式
- set_redir_config
- else
- echo -e "\033[31m设备未检测到Tun内核模块,请尝试其他模式或者安装相关依赖!\033[0m"
- sleep 1
- fi
- set_redir_mod
- ;;
- 3)
- if [ "$firewall_mod" = "iptables" ]; then
- if [ -f /etc/init.d/qca-nss-ecm -a "$systype" = "mi_snapshot" ]; then
- read -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
- echo -e "\033[31m设备未检测到iptables-mod-tproxy模块,请尝试其他模式或者安装相关依赖!\033[0m"
- 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
- echo -e "\033[31m设备未检测到nft_tproxy内核模块,请尝试其他模式或者安装相关依赖!\033[0m"
- sleep 1
- fi
- fi
- set_redir_mod
- ;;
- 4)
- if [ -n "$sup_tun" ]; then
- redir_mod=Tun模式
- set_redir_config
- else
- echo -e "\033[31m设备未检测到Tun内核模块,请尝试其他模式或者安装相关依赖!\033[0m"
- sleep 1
- fi
- set_redir_mod
- ;;
- 5)
- redir_mod='TCP旁路转发'
- set_redir_config
- set_redir_mod
- ;;
- 6)
- redir_mod='T&U旁路转发'
- set_redir_config
- set_redir_mod
- ;;
- 7)
- set_firewall_area
- set_redir_mod
- ;;
- 8)
- set_firewall_vm
- set_redir_mod
- ;;
- 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
- echo -e "\033[31m当前设备未安装nftables或者nftables版本过低(<1.0.2),无法切换!\033[0m"
- fi
- elif [ "$firewall_mod" = 'nftables' ]; then
- if ckcmd iptables; then
- firewall_mod=iptables
- redir_mod=Redir模式
- setconfig redir_mod $redir_mod
- else
- echo -e "\033[31m当前设备未安装iptables,无法切换!\033[0m"
- 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
- echo -e "\033[31m检测不到可用的防火墙应用(iptables/nftables),无法切换!\033[0m"
- fi
- fi
- sleep 1
- setconfig firewall_mod $firewall_mod
- set_redir_mod
- ;;
- *)
- errornum
- ;;
- esac
-}
-set_fw_filter(){ #流量过滤
- [ -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
- echo "-----------------------------------------------"
- echo -e " 1 过滤非常用端口: \033[36m$common_ports\033[0m ————用于过滤P2P流量"
- echo -e " 2 过滤局域网设备: \033[36m$mac_return\033[0m ————使用黑/白名单进行过滤"
- echo -e " 3 过滤QUIC协议: \033[36m$quic_rj\033[0m ————优化视频性能"
- echo -e " 4 过滤CN_IP列表: \033[36m$cn_ip_route\033[0m ————优化性能,不兼容Fake-ip"
- echo -e " 5 自定义透明路由ipv4网段: 适合vlan等复杂网络环境"
- echo -e " 6 自定义保留地址ipv4网段: 需要以保留地址为访问目标的环境"
- echo "-----------------------------------------------"
- echo -e " 0 返回上级菜单 \033[0m"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0)
- ;;
- 1)
- echo "-----------------------------------------------"
- if [ -n "$(pidof CrashCore)" ] && [ "$firewall_mod" = 'iptables' ]; then
- read -p "切换时将停止服务,是否继续?(1/0) > " res
- [ "$res" = 1 ] && "$CRASHDIR"/start.sh stop && set_common_ports
- else
- set_common_ports
- fi
- set_fw_filter
- ;;
- 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
- set_fw_filter
- ;;
- 3)
- echo "-----------------------------------------------"
- if [ -n "$(echo "$redir_mod" | grep -oE '混合|Tproxy|Tun')" ]; then
- if [ "$quic_rj" = "OFF" ]; then
- echo -e "\033[33m已禁止QUIC流量通过ShellCrash内核!!\033[0m"
- quic_rj=ON
- else
- echo -e "\033[33m已取消禁止QUIC协议流量!!\033[0m"
- quic_rj=OFF
- fi
- setconfig quic_rj $quic_rj
- else
- echo -e "\033[33m当前模式默认不会代理UDP流量,无需设置!!\033[0m"
- fi
- sleep 1
- set_fw_filter
- ;;
- 4)
- if [ -n "$(ipset -v 2>/dev/null)" ] || [ "$firewall_mod" = 'nftables' ]; then
- if [ "$cn_ip_route" = "OFF" ]; then
- echo -e "\033[32m已开启CN_IP绕过内核功能!!\033[0m"
- echo -e "\033[31m注意!!!此功能会导致全局模式及一切CN相关规则失效!!!\033[0m"
- cn_ip_route=ON
- sleep 2
- else
- echo -e "\033[33m已禁用CN_IP绕过内核功能!!\033[0m"
- cn_ip_route=OFF
- fi
- setconfig cn_ip_route $cn_ip_route
- else
- echo -e "\033[31m当前设备缺少ipset模块或未使用nftables模式,无法启用绕过功能!!\033[0m"
- sleep 1
- fi
- set_fw_filter
- ;;
- 5)
- set_cust_host_ipv4
- set_fw_filter
- ;;
- 6)
- [ -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"
- echo -e "当前网段:\033[36m$reserve_ipv4\033[0m"
- echo -e "\033[33m地址必须是空格分隔,错误的设置可能导致网络回环或启动报错,请务必谨慎!\033[0m"
- read -p "请输入 > " text
- if [ -n "$(
- echo $text | grep -E "(((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"
- echo -e "已将保留地址网段设为:\033[32m$reserve_ipv4\033[0m"
- setconfig reserve_ipv4 "'$reserve_ipv4'"
- else
- echo -e "\033[31m输入有误,操作已取消!\033[0m"
- fi
- sleep 1
- set_fw_filter
- ;;
- *)
- errornum
- ;;
- esac
-}
-set_common_ports() {
- [ -z "$multiport" ] && multiport='22,80,443,8080,8443'
- echo "-----------------------------------------------"
- echo -e "\033[31m注意:\033[0mMIX模式下,所有fake-ip来源的非常用端口流量不会被过滤"
- [ -n "$common_ports" ] &&
- echo -e "当前放行端口:\033[36m$multiport\033[0m"
- echo "-----------------------------------------------"
- echo -e " 1 启用/关闭端口过滤: \033[36m$common_ports\033[0m"
- echo -e " 2 添加放行端口"
- echo -e " 3 移除指定放行端口"
- echo -e " 4 重置默认放行端口"
- echo -e " 5 重置为旧版放行端口"
- echo -e " 0 返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case $num in
- 1)
- if [ "$common_ports" = ON ];then
- common_ports=OFF
- else
- common_ports=ON
- fi
- setconfig common_ports "$common_ports"
- set_common_ports
- ;;
- 2)
- port_count=$(echo "$multiport" | awk -F',' '{print NF}' )
- if [ "$port_count" -ge 15 ];then
- echo -e "\033[31m最多支持设置放行15个端口,请先减少一些!\033[0m"
- else
- read -p "请输入要放行的端口号 > " port
- if echo ",$multiport," | grep -q ",$port,";then
- echo -e "\033[31m输入错误!请勿重复添加!\033[0m"
- elif [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
- echo -e "\033[31m输入错误!请输入正确的数值(1-65535)!\033[0m"
- else
- multiport=$(echo "$multiport,$port" | sed "s/^,//")
- setconfig multiport "$multiport"
- fi
- fi
- sleep 1
- set_common_ports
- ;;
- 3)
- read -p "请输入要移除的端口号 > " port
- if echo ",$multiport," | grep -q ",$port,";then
- if [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
- echo -e "\033[31m输入错误!请输入正确的数值(1-65535)!\033[0m"
- else
- multiport=$(echo ",$multiport," | sed "s/,$port//; s/^,//; s/,$//")
- setconfig multiport "$multiport"
- fi
- else
- echo -e "\033[31m输入错误!请输入已添加过的端口!\033[0m"
- fi
- sleep 1
- set_common_ports
- ;;
- 4)
- multiport=''
- setconfig multiport
- sleep 1
- set_common_ports
- ;;
- 5)
- multiport='22,80,143,194,443,465,587,853,993,995,5222,8080,8443'
- setconfig multiport "$multiport"
- sleep 1
- set_common_ports
- ;;
- *)
- errornum
- ;;
- esac
-}
-set_cust_host_ipv4() { #自定义ipv4透明路由网段
- [ -z "$replace_default_host_ipv4" ] && replace_default_host_ipv4="OFF"
- . "$CRASHDIR"/starts/fw_getlanip.sh && getlanip
- echo "-----------------------------------------------"
- echo -e "当前默认透明路由的网段为: \033[32m$host_ipv4\033[0m"
- echo -e "当前已添加的自定义网段为:\033[36m$cust_host_ipv4\033[0m"
- echo "-----------------------------------------------"
- echo -e " 1 移除所有自定义网段"
- echo -e " 2 使用自定义网段覆盖默认网段 \033[36m$replace_default_host_ipv4\033[0m"
- echo -e " 0 返回上级菜单"
- read -p "请输入对应的序号或需要额外添加的网段 > " text
- case "$text" in
- 2)
- if [ "$replace_default_host_ipv4" == "OFF" ]; then
- replace_default_host_ipv4="ON"
- else
- replace_default_host_ipv4="OFF"
- fi
- setconfig replace_default_host_ipv4 "$replace_default_host_ipv4"
- set_cust_host_ipv4
- ;;
- 1)
- unset cust_host_ipv4
- setconfig cust_host_ipv4
- set_cust_host_ipv4
- ;;
- 0) ;;
- *)
- if [ -n "$(echo $text | grep -Eo '^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]{1,2}'$)" -a -z "$(echo $cust_host_ipv4 | grep "$text")" ]; then
- cust_host_ipv4="$cust_host_ipv4 $text"
- setconfig cust_host_ipv4 "'$cust_host_ipv4'"
- else
- echo "-----------------------------------------------"
- echo -e "\033[31m请输入正确的网段地址!\033[0m"
- fi
- sleep 1
- set_cust_host_ipv4
- ;;
- esac
-}
-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() {
- echo "-----------------------------------------------"
- echo 已添加的mac地址:
- cat "$CRASHDIR"/configs/mac 2>/dev/null
- echo "-----------------------------------------------"
- echo -e "\033[33m序号 设备IP 设备mac地址 设备名称\033[32m"
- cat $dhcpdir | awk '{print " "NR" "$3,$2,$4}'
- echo -e "\033[0m-----------------------------------------------"
- echo -e "手动输入mac地址时仅支持\033[32mxx:xx:xx:xx:xx:xx\033[0m的形式"
- echo -e " 0 或回车 结束添加"
- echo "-----------------------------------------------"
- read -p "请输入对应序号或直接输入mac地址 > " num
- if [ -z "$num" -o "$num" = 0 ]; then
- i=
- elif [ -n "$(echo $num | grep -aE '^([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
- echo "-----------------------------------------------"
- echo -e "\033[31m已添加的设备,请勿重复添加!\033[0m"
- fi
- add_mac
- 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
- echo "-----------------------------------------------"
- echo -e "\033[31m已添加的设备,请勿重复添加!\033[0m"
- fi
- add_mac
- else
- echo "-----------------------------------------------"
- echo -e "\033[31m输入有误,请重新输入!\033[0m"
- add_mac
- fi
- }
- add_ip() {
- echo "-----------------------------------------------"
- echo "已添加的IP地址(段):"
- cat "$CRASHDIR"/configs/ip_filter 2>/dev/null
- echo "-----------------------------------------------"
- echo -e "\033[33m序号 设备IP 设备名称\033[32m"
- cat $dhcpdir | awk '{print " "NR" "$3,$4}'
- echo -e "\033[0m-----------------------------------------------"
- echo -e "手动输入时仅支持\033[32m 192.168.1.0/24\033[0m 或 \033[32m192.168.1.0\033[0m 的形式"
- echo -e "不支持ipv6地址过滤,如有需求请使用mac地址过滤"
- echo -e " 0 或回车 结束添加"
- echo "-----------------------------------------------"
- read -p "请输入对应序号或直接输入IP地址段 > " num
- if [ -z "$num" -o "$num" = 0 ]; then
- i=
- elif [ -n "$(echo $num | grep -aE '^((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
- echo "-----------------------------------------------"
- echo -e "\033[31m已添加的地址,请勿重复添加!\033[0m"
- fi
- add_ip
- 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
- echo "-----------------------------------------------"
- echo -e "\033[31m已添加的地址,请勿重复添加!\033[0m"
- fi
- add_ip
- else
- echo "-----------------------------------------------"
- echo -e "\033[31m输入有误,请重新输入!\033[0m"
- add_ip
- fi
- }
- del_all() {
- echo "-----------------------------------------------"
- if [ -z "$(cat "$CRASHDIR"/configs/mac "$CRASHDIR"/configs/ip_filter 2>/dev/null)" ]; then
- echo -e "\033[31m列表中没有需要移除的设备!\033[0m"
- sleep 1
- else
- echo -e "请选择需要移除的设备:\033[36m"
- echo -e "\033[33m 设备IP 设备mac地址 设备名称\033[0m"
- i=1
- for dev in $(cat "$CRASHDIR"/configs/mac "$CRASHDIR"/configs/ip_filter 2>/dev/null); do
- get_devinfo
- echo -e " $i \033[32m$dev_ip \033[36m$dev_mac \033[32m$dev_name\033[0m"
- i=$((i + 1))
- done
- echo "-----------------------------------------------"
- echo -e "\033[0m 0 或回车 结束删除"
- read -p "请输入需要移除的设备的对应序号 > " 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=
- elif [ $num -le $mac_filter_rows ]; then
- sed -i "${num}d" "$CRASHDIR"/configs/mac
- echo "-----------------------------------------------"
- echo -e "\033[32m对应设备已移除!\033[0m"
- del_all
- elif [ $num -le $((mac_filter_rows + ip_filter_rows)) ]; then
- num=$((num - mac_filter_rows))
- sed -i "${num}d" "$CRASHDIR"/configs/ip_filter
- echo "-----------------------------------------------"
- echo -e "\033[32m对应设备已移除!\033[0m"
- del_all
- else
- echo "-----------------------------------------------"
- echo -e "\033[31m输入有误,请重新输入!\033[0m"
- del_all
- fi
- fi
- }
- echo "-----------------------------------------------"
- [ -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
- ######
- echo -e "\033[30;47m请在此添加或移除设备\033[0m"
- echo -e "当前过滤方式为:\033[33m$macfilter_type模式\033[0m"
- echo -e "仅列表内设备流量\033[36m$fw_filter_lan_scrip经过\033[0m内核"
- if [ -n "$(cat "$CRASHDIR"/configs/mac)" ]; then
- echo "-----------------------------------------------"
- echo -e "当前已过滤设备为:\033[36m"
- echo -e "\033[33m 设备mac/ip地址 设备名称\033[0m"
- for dev in $(cat "$CRASHDIR"/configs/mac 2>/dev/null); do
- get_devinfo
- echo -e "\033[36m$dev_mac \033[0m$dev_name"
- done
- for dev in $(cat "$CRASHDIR"/configs/ip_filter 2>/dev/null); do
- get_devinfo
- echo -e "\033[32m$dev_ip \033[0m$dev_name"
- done
- echo "-----------------------------------------------"
- fi
- echo -e " 1 切换为\033[33m$fw_filter_lan_over模式\033[0m"
- echo -e " 2 \033[32m添加指定设备(mac地址)\033[0m"
- echo -e " 3 \033[32m添加指定设备(IP地址/网段)\033[0m"
- echo -e " 4 \033[36m移除指定设备\033[0m"
- echo -e " 9 \033[31m清空整个列表\033[0m"
- echo -e " 0 返回上级菜单"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0) ;;
- 1)
- macfilter_type=$fw_filter_lan_over
- setconfig macfilter_type $macfilter_type
- echo "-----------------------------------------------"
- echo -e "\033[32m已切换为$macfilter_type模式!\033[0m"
- fw_filter_lan
- ;;
- 2)
- add_mac
- fw_filter_lan
- ;;
- 3)
- add_ip
- fw_filter_lan
- ;;
- 4)
- del_all
- fw_filter_lan
- ;;
- 9)
- : >"$CRASHDIR"/configs/mac
- : >"$CRASHDIR"/configs/ip_filter
- echo "-----------------------------------------------"
- echo -e "\033[31m设备列表已清空!\033[0m"
- fw_filter_lan
- ;;
- *)
- errornum
- ;;
- esac
-}
-set_adv_config() { #端口设置
- . "$CFG_PATH" >/dev/null
- [ -z "$secret" ] && secret=未设置
- [ -z "$table" ] && table=100
- [ -z "$authentication" ] && auth=未设置 || auth=******
- inputport() {
- read -p "请输入端口号(1-65535) > " portx
- . "$CRASHDIR"/menus/check_port.sh #加载测试函数
- if check_port "$portx"; then
- setconfig "$xport" "$portx"
- echo -e "\033[32m设置成功!!!\033[0m"
- set_adv_config
- else
- sleep 1
- fi
- }
- echo "-----------------------------------------------"
- echo -e " 1 修改Http/Sock5端口: \033[36m$mix_port\033[0m"
- echo -e " 2 设置Http/Sock5密码: \033[36m$auth\033[0m"
- echo -e " 3 修改Redir/Tproxy端口:\033[36m$redir_port,$((redir_port + 1))\033[0m"
- echo -e " 4 修改DNS监听端口: \033[36m$dns_port\033[0m"
- echo -e " 5 修改面板访问端口: \033[36m$db_port\033[0m"
- echo -e " 6 设置面板访问密码: \033[36m$secret\033[0m"
- echo -e " 8 自定义本机host地址: \033[36m$host\033[0m"
- echo -e " 9 自定义路由表: \033[36m$table,$((table + 1))\033[0m"
- echo -e " 0 返回上级菜单"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0) ;;
- 1)
- xport=mix_port
- inputport
- ;;
- 2)
- echo "-----------------------------------------------"
- echo -e "格式必须是\033[32m 用户名:密码 \033[0m的形式,注意用小写冒号分隔!"
- echo -e "请尽量不要使用特殊符号!避免产生未知错误!"
- echo "输入 0 删除密码"
- echo "-----------------------------------------------"
- read -p "请输入Http/Sock5用户名及密码 > " input
- if [ "$input" = "0" ]; then
- authentication=""
- setconfig authentication
- echo 密码已移除!
- else
- if [ "$local_proxy" = "ON" -a "$local_type" = "环境变量" ]; then
- echo "-----------------------------------------------"
- echo -e "\033[33m请先禁用本机劫持功能或使用增强模式!\033[0m"
- sleep 1
- else
- authentication=$(echo $input | grep :)
- if [ -n "$authentication" ]; then
- setconfig authentication "'$authentication'"
- echo -e "\033[32m设置成功!!!\033[0m"
+# 功能设置
+settings() {
+ while true; do
+ # 获取设置默认显示
+ [ -z "$skip_cert" ] && skip_cert=ON
+ [ -z "$sniffer" ] && {
+ sniffer=OFF
+ echo "$crashcore" | grep -q 'singbox' && sniffer=ON
+ }
+ [ -z "$dns_mod" ] && dns_mod='redir_host'
+
+ comp_box "\033[30;47m$SET_MENU_TITLE\033[0m"
+ 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\t$SET_MENU_FW_FILTER_DESC"
+ [ "$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 "7) $SET_MENU_IPV6\t\033[36m$ipv6_redir\033[0m"
+ btm_box "" \
+ "a) \033[31m$SET_MENU_RESET\033[0m" \
+ "b) \033[36m$SET_MENU_LANG\033[0m" \
+ "c) \033[33m$SET_MENU_UI\033[0m" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ if [ "$USER" != root ] && [ "$USER" != admin ]; then
+ comp_box "$SET_WARN_NONROOT"
+ btm_box "1) $SET_YES" \
+ "0) $SET_NO_BACK"
+ read -r -p "$COMMON_INPUT> " res
+ if [ "$res" = 1 ]; then
+ set_redir_mod
else
- echo -e "\033[31m输入有误,请重新输入!\033[0m"
+ 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 "$SET_SKIP_CERT_NOW\033[33m$SET_DISABLED\033[0m$SET_SKIP_CERT_ENABLE_Q"
+ else
+ content_line "$SET_SKIP_CERT_NOW\033[33m$SET_ENABLED\033[0m$SET_SKIP_CERT_DISABLE_Q"
+ fi
+ separator_line "="
+ btm_box "1) $SET_YES" \
+ "0) $SET_NO_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ if [ "$num" = 1 ]; then
+ if [ "$skip_cert" = OFF ]; then
+ skip_cert=ON
+ msg_alert "\033[33m$SET_SKIP_CERT_ON\033[0m"
+ else
+ skip_cert=OFF
+ msg_alert "\033[33m$SET_SKIP_CERT_OFF\033[0m"
+ fi
+ setconfig skip_cert $skip_cert
+ else
+ continue
+ fi
+ ;;
+ 5)
+ if [ "$sniffer" = "OFF" ]; then
+ comp_box "$SET_SNIFFER_NOW\033[33m$SET_DISABLED\033[0m$SET_SNIFFER_ENABLE_Q"
+ btm_box "1) $SET_YES" \
+ "0) $SET_NO_BACK"
+ 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
+ top_box "$SET_SNIFFER_CORE_SWITCH" \
+ ""
+ fi
+ sniffer=ON
+ else
+ continue
+ fi
+ elif [ "$crashcore" = clashpre ] && [ "$dns_mod" = redir_host ]; then
+ msg_alert "\033[31m$SET_SNIFFER_LOCKED\033[0m"
+ continue
+ else
+ comp_box "$SET_SNIFFER_NOW\033[33m$SET_ENABLED\033[0m$SET_SNIFFER_DISABLE_Q"
+ btm_box "1) $SET_YES" \
+ "0) $SET_NO_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ if [ "$num" = 1 ]; then
+ sniffer=OFF
+ line_break
+ separator_line "="
+ else
+ continue
fi
fi
- fi
- set_adv_config
- ;;
- 3)
- xport=redir_port
- inputport
- ;;
- 4)
- xport=dns_port
- inputport
- ;;
- 5)
- xport=db_port
- inputport
- ;;
- 6)
- read -p "请输入面板访问密码(输入0删除密码) > " secret
- if [ -n "$secret" ]; then
- [ "$secret" = "0" ] && secret=""
- setconfig secret $secret
- echo -e "\033[32m设置成功!!!\033[0m"
- fi
- set_adv_config
- ;;
- 8)
- echo "-----------------------------------------------"
- echo -e "\033[33m如果你的局域网网段不是192.168.x或172.16.x或10.x开头,请务必修改!\033[0m"
- echo -e "\033[31m设置后如本机host地址有变动,请务必重新修改!\033[0m"
- echo "-----------------------------------------------"
- read -p "请输入自定义host地址(输入0移除自定义host) > " host
- if [ "$host" = "0" ]; then
- host=""
- setconfig host "$host"
- echo -e "\033[32m已经移除自定义host地址,请重新运行脚本以自动获取host!!!\033[0m"
+ setconfig sniffer "$sniffer"
+ btm_box "\033[32m$COMMON_SUCCESS\033[0m"
+ sleep 1
+ ;;
+ 6)
+ if pidof CrashCore >/dev/null; then
+ comp_box "\033[33m$SET_CORE_RUNNING\033[0m" \
+ "$SET_CORE_STOP_CONFIRM"
+ btm_box "1) $SET_YES" \
+ "0) $SET_NO_BACK"
+ 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
+ ;;
+ 7)
+ set_ipv6
+ ;;
+ a)
+ BACK_TAR="$CRASHDIR/configs.tar.gz"
+ comp_box "1) $SET_BACKUP" \
+ "2) $SET_RESTORE" \
+ "3) $SET_RESET" \
+ "" \
+ "0) $COMMON_BACK"
+ 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
+ separator_line "="
+ 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
+ ;;
+ *)
+ errornum
+ continue
+ ;;
+ esac
+ content_line "\033[33m$SET_NEED_RESTART\033[0m"
+ separator_line "="
+ line_break
+ sleep 1
exit 0
- elif [ -n "$(echo $host | grep -E -o '\<([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"
- echo -e "\033[32m设置成功!!!\033[0m"
- else
- host=""
- echo -e "\033[31m输入错误,请仔细核对!!!\033[0m"
- fi
- sleep 1
- set_adv_config
- ;;
- 9)
- echo "-----------------------------------------------"
- echo -e "\033[33m仅限Tproxy、Tun或混合模式路由表出现冲突时才需要设置!\033[0m"
- read -p "请输入路由表地址(不明勿动!建议102-125之间) > " table
- if [ -n "$table" ]; then
- [ "$table" = "0" ] && table="100"
- setconfig table "$table"
- echo -e "\033[32m设置成功!!!\033[0m"
- fi
- set_adv_config
- ;;
- *)
- errornum
- ;;
- esac
+ ;;
+ b)
+ comp_box "1) 简体中文" \
+ "2) English" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 0)
+ continue
+ ;;
+ 1)
+ echo chs >"$CRASHDIR"/configs/i18n.cfg
+ msg_alert "\033[32m切换成功,请重新执行脚本!\033[0m"
+ ;;
+ 2)
+ echo en >"$CRASHDIR"/configs/i18n.cfg
+ msg_alert "\033[32mLanguage switched successfully! Please re-run the script!\033[0m"
+ ;;
+ esac
+ line_break
+ exit 0
+ ;;
+ c)
+ comp_box "1) New Design by Sofia-Riese" \
+ "2) TUI-lite" \
+ "" \
+ "0) $COMMON_BACK"
+ 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
+ msg_alert "\033[32m$SET_SWITCH_OK\033[0m"
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
}
-set_firewall_area() { #路由范围设置
- [ -z "$vm_redir" ] && vm_redir='OFF'
- echo "-----------------------------------------------"
- echo -e "\033[31m注意:\033[0m基于桥接网卡的Docker/虚拟机流量,请单独启用!"
- echo -e "\033[33m如你使用了第三方DNS如smartdns等,请勿启用本机劫持或使用shellcrash用户执行!\033[0m"
- echo "-----------------------------------------------"
- echo -e " 1 \033[32m仅劫持局域网流量\033[0m"
- echo -e " 2 \033[36m仅劫持本机流量\033[0m"
- echo -e " 3 \033[32m劫持局域网+本机流量\033[0m"
- echo -e " 4 不配置流量劫持(纯净模式)\033[0m"
- #echo -e " 5 \033[33m转发局域网流量到旁路由设备\033[0m"
- echo -e " 0 返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
+
+set_redir_config() {
+ setconfig redir_mod "$redir_mod"
+ setconfig dns_mod "$dns_mod"
+ msg_alert "\033[36m$SET_REDIR_APPLIED $redir_mod $SET_MODE_SUFFIX\033[0m"
+}
+
+# 路由模式设置
+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'
+ [ -z "$vm_redir" ] && vm_redir='OFF'
+ firewall_area_dsc=$(echo "$SET_FW_AREA_DESC($bypass_host)" | cut -d'|' -f$firewall_area)
+ comp_box "\033[33m$SET_REDIR_RESTART_HINT\033[0m" \
+ "$SET_REDIR_CURRENT\033[47;30m$redir_mod$MENU_MOD\033[0m; $SET_CORE_CURRENT\033[47;30m$crashcore\033[0m"
+ [ "$firewall_area" -le 3 ] && {
+ content_line "1) $SET_SET_TO\033[32m$SET_REDIR_REDIR\033[0m:\t$SET_REDIR_REDIRDES"
+ content_line "2) $SET_SET_TO\033[36m$SET_REDIR_MIX\033[0m:\t$SET_REDIR_MIXDES"
+ content_line "3) $SET_SET_TO\033[32m$SET_REDIR_TPROXY\033[0m:\t$SET_REDIR_TPROXYDES"
+ content_line "4) $SET_SET_TO\033[33m$SET_REDIR_TUN\033[0m:\t$SET_REDIR_TUNDES"
+ content_line ""
+ }
+ [ "$firewall_area" = 5 ] && {
+ content_line "5) \033[32m$SET_BYPASS_TCP\033[0m: $SET_BYPASS_TCP_DESC"
+ content_line "6) \033[36m$SET_BYPASS_TU\033[0m: $SET_BYPASS_TU_DESC"
+ content_line ""
+ }
+ btm_box "7) $SET_FW_AREA:\t\033[47;30m$firewall_area_dsc\033[0m" \
+ "8) $SET_VM_REDIR:\t\033[47;30m$vm_redir\033[0m" \
+ "9) $SET_FW_SWITCH:\t\033[47;30m$firewall_mod\033[0m" \
+ "" \
+ "0) $COMMON_BACK"
+ 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
+ msg_alert "\033[31m${SET_NO_MOD}TUN\033[0m" \
+ "\033[31m$SET_NO_MOD2\033[0m"
+ 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
+ msg_alert "\033[31m${SET_NO_MOD}iptables-mod-tproxy\033[0m" \
+ "\033[31m$SET_NO_MOD2\033[0m"
+ 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
+ msg_alert "\033[31m${SET_NO_MOD}nft_tproxy\033[0m" \
+ "\033[31m$SET_NO_MOD2\033[0m"
+ fi
+ fi
+ ;;
+ 4)
+ if [ -n "$sup_tun" ]; then
+ redir_mod=Tun
+ set_redir_config
+ else
+ msg_alert "\033[31m$SET_NO_TUN\033[0m"
+ fi
+ ;;
+ 5)
+ redir_mod='$SET_BYPASS_TCP'
+ set_redir_config
+ ;;
+ 6)
+ redir_mod='$SET_BYPASS_TU'
+ 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
+ msg_alert "\033[31m$FW_NO_NFTABLES\033[0m"
+ fi
+ elif [ "$firewall_mod" = 'nftables' ]; then
+ if ckcmd iptables; then
+ firewall_mod=iptables
+ redir_mod=Redir
+ setconfig redir_mod $redir_mod
+ else
+ msg_alert "\033[31m$FW_NO_IPTABLES\033[0m"
+ 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
+ msg_alert "\033[31m$FW_NO_FIREWALL_BACKEND\033[0m"
+ fi
+ fi
+ setconfig firewall_mod "$firewall_mod"
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
+}
+
+inputport() {
+ local protocol="${1:-all}"
+ line_break
+ read -r -p "$INPUT_PORT(1~65535)> " portx
+ . "$CRASHDIR"/menus/check_port.sh
+
+ if ! check_port "$portx" "$protocol"; then
+ msg_alert "\033[31m$COMMON_FAILED\033[0m"
+ return 1
+ fi
+
+ local ports_to_check=""
+ [ "$xport" != "mix_port" ] && ports_to_check="$ports_to_check|$mix_port"
+ [ "$xport" != "redir_port" ] && ports_to_check="$ports_to_check|$redir_port"
+ [ "$xport" != "dns_port" ] && ports_to_check="$ports_to_check|$dns_port"
+ [ "$xport" != "db_port" ] && ports_to_check="$ports_to_check|$db_port"
+
+ if echo "$ports_to_check|" | grep -q "|$portx|"; then
+ msg_alert "\033[31m$CHECK_PORT_DUP_ERR\033[0m"
+ return 1
+ fi
+
+ setconfig "$xport" "$portx"
+ msg_alert "\033[32m$COMMON_SUCCESS\033[0m"
+ return 0
+}
+
+# 端口设置
+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="******"
+ comp_box "1) $ADV_HTTP_PORT:\t\033[36m$mix_port\033[0m" \
+ "2) $ADV_HTTP_AUTH:\t\033[36m$auth\033[0m" \
+ "3) $ADV_REDIR_PORT:\t\033[36m$redir_port,$((redir_port + 1))\033[0m" \
+ "4) $ADV_DNS_PORT:\t\t\033[36m$dns_port\033[0m" \
+ "5) $ADV_PANEL_PORT:\t\t\033[36m$db_port\033[0m" \
+ "6) $ADV_PANEL_PASS:\t\t\033[36m$secret\033[0m" \
+ "8) $ADV_HOST:\t\033[36m$host\033[0m" \
+ "9) $ADV_TABLE:\t\t\033[36m$table,$((table + 1))\033[0m" \
+ "" \
+ "0) $COMMON_BACK"
+ 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)
+ comp_box "$ADV_AUTH_FORMAT_DESC" \
+ "$ADV_AUTH_WARN" \
+ "$ADV_AUTH_REMOVE_HINT"
+ read -r -p "$ADV_AUTH_INPUT> " input
+ if [ "$input" = "0" ]; then
+ authentication=""
+ setconfig authentication
+ msg_alert "\033[32m$ADV_AUTH_REMOVED\033[0m"
+ else
+ if [ "$local_proxy" = "ON" ] && [ "$local_type" = "$LOCAL_TYPE_ENV" ]; then
+ msg_alert "\033[33m$ADV_AUTH_ENV_CONFLICT\033[0m"
+ else
+ authentication=$(echo "$input" | grep :)
+ if [ -n "$authentication" ]; then
+ setconfig authentication "'$authentication'"
+ msg_alert "\033[32m$COMMON_SUCCESS\033[0m"
+ else
+ msg_alert "\033[31m$ADV_AUTH_INVALID\033[0m"
+ fi
+ fi
+ fi
+ ;;
+ 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 tcp
+ 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=""
+ if setconfig secret "$secret"; then
+ common_success
+ else
+ common_failed
+ fi
+ fi
+ ;;
+ 8)
+ comp_box "\033[33m$ADV_HOST_WARN_LAN\033[0m" \
+ "\033[31m$ADV_HOST_WARN_CHANGE\033[0m"
+ read -r -p "$ADV_HOST_INPUT> " host
+ if [ "$host" = "0" ]; then
+ host=""
+ setconfig host "$host"
+ msg_alert "\033[32m$ADV_HOST_REMOVED\033[0m"
+ line_break
+ 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
+ if setconfig host "$host"; then
+ common_success
+ else
+ common_failed
+ fi
+ else
+ host=""
+ msg_alert "\033[31m$ADV_HOST_INVALID\033[0m"
+ fi
+ ;;
+ 9)
+ comp_box "\033[33m$ADV_TABLE_WARN\033[0m"
+ read -r -p "$ADV_TABLE_INPUT> " table
+ if [ -n "$table" ]; then
+ [ "$table" = "0" ] && table="100"
+ if setconfig table "$table"; then
+ common_success
+ else
+ common_failed
+ fi
+ fi
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
+}
+
+set_firewall_area() {
+ while true; do
+ comp_box "\033[33m$FW_AREA_NOTE_1\033[0m" \
+ "\033[33m$FW_AREA_NOTE_2\033[0m" \
+ "" \
+ "$SET_FW_AREA_CURRENT$firewall_area_dsc"
+ btm_box "1) \033[32m$FW_AREA_LAN\033[0m" \
+ "2) \033[36m$FW_AREA_LOCAL\033[0m" \
+ "3) \033[32m$FW_AREA_BOTH\033[0m" \
+ "4) $FW_AREA_NONE" \
+ "" \
+ "0) $COMMON_BACK"
+ 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
+
+ common_success
+ ;;
+ 5)
+ comp_box "\033[31m$SET_WARN\033[0m" \
+ "$SET_BYPASS_WARN_1" \
+ "$SET_BYPASS_WARN_2" \
+ "$SET_BYPASS_WARN_3" \
+ "\033[33m$SET_DESC\033[0m" \
+ "$SET_BYPASS_DESC_1" \
+ "$SET_BYPASS_DESC_2"
+ read -r -p "$SET_INPUT_BYPASS_IPV4> " bypass_host
+ [ -n "$bypass_host" ] && {
+ firewall_area=$num
+ setconfig firewall_area "$firewall_area"
+ setconfig bypass_host "$bypass_host"
+ redir_mod=$SET_BYPASS_TCP
+ setconfig redir_mod $redir_mod
+ }
+ ;;
+ *)
+ errornum
+ ;;
+ 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' ' ')
+ comp_box "$VM_DETECT_DESC\033[32m$vm_ipv4\033[0m"
+ btm_box "1) \033[32m$VM_ENABLE_AUTO\033[0m" \
+ "2) \033[36m$VM_ENABLE_MANUAL\033[0m" \
+ "3) \033[31m$VM_DISABLE\033[0m" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
case "$num" in
- 0) ;;
- [1-4])
- [ $firewall_area -ge 4 ] && {
- redir_mod=Redir模式
- setconfig redir_mod $redir_mod
- }
- [ "$num" = 4 ] && {
- redir_mod=纯净模式
- setconfig redir_mod $redir_mod
- }
- firewall_area=$num
- setconfig firewall_area $firewall_area
- ;;
- 5)
- echo "-----------------------------------------------"
- echo -e "\033[31m注意:\033[0m此功能存在多种风险如无网络基础请勿尝试!"
- echo -e "\033[33m说明:\033[0m此功能不启动内核仅配置防火墙转发,且子设备无需额外设置网关DNS"
- echo -e "\033[33m说明:\033[0m支持防火墙分流及设备过滤,支持部分定时任务,但不支持ipv6!"
- echo -e "\033[31m注意:\033[0m如需代理UDP,请确保旁路由运行了支持UDP代理的模式!"
- echo -e "\033[31m注意:\033[0m如使用systemd方式启动,内核依然会空载运行,建议使用保守模式!"
- echo "-----------------------------------------------"
- read -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 ;;
+ 1)
+ if [ -n "$vm_ipv4" ]; then
+ vm_redir=ON
+ common_success
+ else
+ msg_alert "\033[33m$VM_NO_NET_DETECTED\033[0m"
+ set_firewall_vm
+ return
+ fi
+
+ ;;
+ 2)
+ comp_box "$VM_INPUT_DESC_1" \
+ "$VM_INPUT_DESC_2 \033[32m10.88.0.0/16 172.17.0.0/16\033[0m" \
+ "" \
+ "$SET_TIPS_ENTER_BACK"
+ read -r -p "$VM_INPUT_NET> " text
+ [ -n "$text" ] && vm_ipv4="$text" && vm_redir=ON
+ ;;
+ 3)
+ vm_redir=OFF
+ vm_ipv4=''
+ ;;
+ *) return ;;
esac
- sleep 1
-}
-set_firewall_vm(){
- if [ -n "$vm_ipv4" ]; then
- vm_des='当前劫持'
- else
- 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' ' ')
- vm_des='当前获取到'
- fi
- echo "-----------------------------------------------"
- echo -e "$vm_des的容器/虚拟机网段为:\033[32m$vm_ipv4\033[0m"
- echo -e "如未包含容器网段,请先运行容器再运行脚本或者手动设置网段"
- echo "-----------------------------------------------"
- echo -e " 1 \033[32m启用劫持并使用默认网段\033[0m"
- echo -e " 2 \033[36m启用劫持并自定义网段\033[0m"
- echo -e " 3 \033[31m禁用劫持\033[0m"
- echo -e " 0 返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- 1)
- if [ -n "$vm_ipv4" ]; then
- vm_redir=ON
- else
- echo -e "\033[33m请先运行容器再运行脚本或者手动设置网段\033[0m"
- fi
- ;;
- 2)
- echo -e "多个网段请用空格连接,可运行容器后使用【ip route】命令查看网段地址"
- echo -e "示例:\033[32m10.88.0.0/16 172.17.0.0/16\033[0m"
- read -p "请输入自定义网段 > " text
- [ -n "$text" ] && vm_ipv4=$text && vm_redir=ON
- ;;
- 3)
- vm_redir=OFF
- unset vm_ipv4
- ;;
- *) ;;
- esac
- setconfig vm_redir $vm_redir
+ common_success
+ setconfig vm_redir "$vm_redir"
setconfig vm_ipv4 "'$vm_ipv4'"
}
-set_ipv6() { #ipv6设置
- [ -z "$ipv6_redir" ] && ipv6_redir=OFF
- [ -z "$ipv6_dns" ] && ipv6_dns=ON
- echo "-----------------------------------------------"
- echo -e " 1 ipv6透明路由: \033[36m$ipv6_redir\033[0m ——劫持ipv6流量"
- [ "$disoverride" != "1" ] && echo -e " 2 ipv6-DNS解析: \033[36m$ipv6_dns\033[0m ——决定内置DNS是否返回ipv6地址"
- echo -e " 0 返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0) ;;
- 1)
- if [ "$ipv6_redir" = "OFF" ]; then
- ipv6_support=ON
- ipv6_redir=ON
- sleep 2
- else
- ipv6_redir=OFF
- fi
- setconfig ipv6_redir $ipv6_redir
- setconfig ipv6_support $ipv6_support
- set_ipv6
- ;;
- 2)
- [ "$ipv6_dns" = "OFF" ] && ipv6_dns=ON || ipv6_dns=OFF
- setconfig ipv6_dns $ipv6_dns
- set_ipv6
- ;;
- *)
- errornum
- ;;
- esac
+
+# ipv6设置
+set_ipv6() {
+ while true; do
+ [ -z "$ipv6_redir" ] && ipv6_redir=OFF
+ [ -z "$ipv6_dns" ] && ipv6_dns=ON
+
+ top_box "1) $IPV6_REDIR:\t\033[36m$ipv6_redir\033[0m"
+ [ "$disoverride" != "1" ] && content_line "2) $IPV6_DNS:\t\033[36m$ipv6_dns\033[0m"
+ btm_box "" \
+ "0) $COMMON_BACK"
+ 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"
+ common_success
+ ;;
+ 2)
+ [ "$ipv6_dns" = OFF ] && ipv6_dns=ON || ipv6_dns=OFF
+ if setconfig ipv6_dns "$ipv6_dns"; then
+ common_success
+ else
+ common_failed
+ fi
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
}
diff --git a/scripts/menus/4_setboot.sh b/scripts/menus/4_setboot.sh
index d20f70e0..ec8a5721 100644
--- a/scripts/menus/4_setboot.sh
+++ b/scripts/menus/4_setboot.sh
@@ -4,8 +4,13 @@
[ -n "$__IS_MODULE_4_SETBOOT_LOADED" ] && return
__IS_MODULE_4_SETBOOT_LOADED=1
+load_lang setboot
+
allow_autostart() {
- [ -f /etc/rc.common -a "$(cat /proc/1/comm)" = "procd" ] && /etc/init.d/shellcrash enable
+ 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
@@ -24,160 +29,225 @@ disable_autostart() {
setboot() {
while true; do
[ -z "$start_old" ] && start_old=OFF
- [ -z "$start_delay" -o "$start_delay" = 0 ] && delay=未设置 || delay="${start_delay}秒"
- check_autostart && auto_set="\033[33m禁止" || auto_set="\033[32m允许"
+
+ if [ -z "$start_delay" ] || [ "$start_delay" = 0 ]; then
+ delay="$SETBOOT_NOT_SET"
+ else
+ delay="${start_delay}$SETBOOT_SECOND"
+ fi
+
+ check_autostart && auto_set="ON" || auto_set="OFF"
[ "${BINDIR}" = "$CRASHDIR" ] && mini_clash=OFF || mini_clash=ON
[ -z "$network_check" ] && network_check=ON
- echo "-----------------------------------------------"
- echo -e "\033[30;47m欢迎使用启动设置菜单:\033[0m"
- echo "-----------------------------------------------"
- echo -e " 1 ${auto_set}\033[0mShellCrash开机启动"
- echo -e " 2 使用保守模式: \033[36m$start_old\033[0m ————基于定时任务(每分钟检测)"
- echo -e " 3 设置自启延时: \033[36m$delay\033[0m ————用于解决自启后服务受限"
- echo -e " 4 启用小闪存模式: \033[36m$mini_clash\033[0m ————用于闪存空间不足的设备"
- [ "${BINDIR}" != "$CRASHDIR" ] && echo -e " 5 设置小闪存目录: \033[36m${BINDIR}\033[0m"
- echo -e " 6 自启网络检查: \033[36m$network_check\033[0m ————禁用则跳过自启时网络检查"
- echo "-----------------------------------------------"
- echo -e " 0 \033[0m返回上级菜单\033[0m"
- read -p "请输入对应数字 > " num
- echo "-----------------------------------------------"
+ comp_box "\033[30;47m$SETBOOT_TITLE\033[0m"
+ content_line "1) $SETBOOT_ITEM_AUTO \033[36m$(printf '%-4s' "$auto_set")\033[0m"
+ content_line "2) $SETBOOT_ITEM_OLD \033[36m$(printf '%-4s' "$start_old")\033[0m $SETBOOT_ITEM_OLD_DESC"
+ content_line "3) $SETBOOT_ITEM_DELAY \033[36m$(printf '%-7s' "$delay")\033[0m $SETBOOT_ITEM_DELAY_DESC"
+ content_line "4) $SETBOOT_ITEM_MINI \033[36m$(printf '%-4s' "$mini_clash")\033[0m $SETBOOT_ITEM_MINI_DESC"
+ [ "${BINDIR}" != "$CRASHDIR" ] && content_line "5) $SETBOOT_ITEM_MINI_DIR \033[36m${BINDIR}\033[0m"
+ btm_box "6) $SETBOOT_ITEM_NETCHK \033[36m$(printf '%-4s' "$network_check")\033[0m $SETBOOT_ITEM_NETCHK_DESC" \
+ "7) $SETBOOT_VIEW_LOG" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
case "$num" in
"" | 0)
break
;;
1)
+
if check_autostart; then
# 禁止自启动:删除各系统的启动项
disable_autostart
- echo -e "\033[33m已禁止ShellCrash开机启动!\033[0m"
+ msg_alert "\033[33m$SETBOOT_AUTO_OFF\033[0m"
else
# 允许自启动:配置各系统的启动项
allow_autostart
- echo -e "\033[32m已设置ShellCrash开机启动!\033[0m"
+ msg_alert "\033[32m$SETBOOT_AUTO_ON\033[0m"
fi
;;
2)
if [ "$start_old" = "OFF" ] >/dev/null 2>&1; then
- echo -e "\033[33m改为使用保守模式启动服务!!\033[0m"
disable_autostart
start_old=ON
setconfig start_old "$start_old"
"$CRASHDIR"/start.sh stop
+ msg_alert "\033[33m$SETBOOT_OLDMODE_ON\033[0m"
else
if grep -qE 'procd|systemd|s6' /proc/1/comm || rc-status -r >/dev/null 2>&1; then
- echo -e "\033[32m改为使用系统守护进程启动服务!!\033[0m"
- "$CRASHDIR"/start.sh cronset "ShellCrash初始化"
+ "$CRASHDIR"/start.sh cronset "$SETBOOT_CRON_INIT"
start_old=OFF
setconfig start_old "$start_old"
"$CRASHDIR"/start.sh stop
-
+ msg_alert "\033[32m$SETBOOT_OLDMODE_OFF\033[0m"
else
- echo -e "\033[31m当前设备不支持以其他模式启动!!\033[0m"
+ msg_alert "\033[31m$SETBOOT_MODE_UNSUPPORTED\033[0m"
fi
fi
- sleep 1
;;
3)
- echo -e "\033[33m如果你的设备启动后可以正常使用,则无需设置!!\033[0m"
- echo -e "\033[36m推荐设置为30~120秒之间,请根据设备问题自行试验\033[0m"
- read -p "请输入启动延迟时间(0~300秒) > " sec
+ comp_box "\033[33m$SETBOOT_DELAY_HINT1\033[0m" \
+ "\033[36m$SETBOOT_DELAY_HINT2\033[0m"
+ read -r -p "$SETBOOT_DELAY_INPUT> " sec
case "$sec" in
[0-9] | [0-9][0-9] | [0-2][0-9][0-9] | 300)
start_delay=$sec
- setconfig start_delay $sec
- echo -e "\033[32m设置成功!\033[0m"
+ setconfig start_delay "$sec"
+ msg_alert "\033[32m$SETBOOT_SET_OK\033[0m"
;;
*)
- echo -e "\033[31m输入有误,或超过300秒,请重新输入!\033[0m"
+ msg_alert "\033[31m$SETBOOT_DELAY_INVALID\033[0m"
;;
esac
- 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}')
if [ "$mini_clash" = "OFF" ]; then
if [ "$dir_size" -gt 20480 ]; then
- echo -e "\033[33m您的设备空间充足(>20M),无需开启!\033[0m"
- elif [ "$start_old" != 'ON' -a "$(cat /proc/1/comm)" = "systemd" ]; then
- echo -e "\033[33m不支持systemd启动模式,请先启用保守模式!\033[0m"
+ msg_alert "\033[33m$SETBOOT_MINI_NEEDED_NO\033[0m"
+ elif [ "$start_old" != 'ON' ] && [ "$(cat /proc/1/comm)" = "systemd" ]; then
+ msg_alert "\033[33m$SETBOOT_SYSTEMD_WARN\033[0m"
else
[ "$BINDIR" = "$CRASHDIR" ] && BINDIR="$TMPDIR"
- echo -e "\033[32m已经启用小闪存功能!\033[0m"
- echo -e "如需更换目录,请使用【设置小闪存目录】功能\033[0m"
+ msg_alert "\033[32m$SETBOOT_MINI_ENABLED\033[0m" \
+ "$SETBOOT_MINI_DIR_HINT\033[0m"
fi
else
if [ "$dir_size" -lt 8192 ]; then
- echo -e "\033[31m您的设备剩余空间不足8M,停用后可能无法正常运行!\033[0m"
- read -p "确认停用此功能?(1/0) > " res
- [ "$res" = 1 ] && BINDIR="$CRASHDIR" && echo -e "\033[33m已经停用小闪存功能!\033[0m"
+ comp_box "\033[31m$SETBOOT_MINI_DISABLE_WARN\033[0m" \
+ "$SETBOOT_MINI_DISABLE_CONFIRM"
+ btm_box "1) $SETBOOT_YES" \
+ "0) $SETBOOT_NO_BACK"
+ read -r -p "$COMMON_INPUT> " res
+ if [ "$res" = 1 ]; then
+ BINDIR="$CRASHDIR"
+ msg_alert "\033[33m$SETBOOT_MINI_DISABLED\033[0m"
+ else
+ continue
+ fi
else
rm -rf /tmp/ShellCrash
BINDIR="$CRASHDIR"
- echo -e "\033[33m已经停用小闪存功能!\033[0m"
+ msg_alert "\033[33m$SETBOOT_MINI_DISABLED\033[0m"
fi
fi
- setconfig BINDIR "$BINDIR" "$CRASHDIR"/configs/command.env
+ sed -i "s#BINDIR=.*#BINDIR=$BINDIR#" "$CRASHDIR"/configs/command.env
sleep 1
;;
5)
- echo -e "\033[33m如设置到内存,则每次开机后都自动重新下载相关文件\033[0m"
- echo -e "\033[33m请确保安装源可用裸连,否则会导致启动失败\033[0m"
- echo " 1 使用内存(/tmp)"
- echo " 2 选择U盘目录"
- echo " 3 自定义目录"
- read -p "请输入相应数字 > " num
- case "$num" in
- 1)
- BINDIR="$TMPDIR"
- ;;
- 2)
- set_usb_dir() {
- echo "请选择安装目录"
- du -hL /mnt | awk '{print " "NR" "$2" "$1}'
- read -p "请输入相应数字 > " num
- BINDIR=$(du -hL /mnt | awk '{print $2}' | sed -n "$num"p)
- if [ -z "$BINDIR" ]; then
- echo "\033[31m输入错误!请重新设置!\033[0m"
- set_usb_dir
+ while true; do
+ comp_box "\033[33m$SETBOOT_BINDIR_HINT1\033[0m" \
+ "\033[33m$SETBOOT_BINDIR_HINT2\033[0m"
+ btm_box "1) $SETBOOT_BINDIR_TMP" \
+ "2) $SETBOOT_BINDIR_USB" \
+ "3) $SETBOOT_BINDIR_CUSTOM" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ BINDIR="$TMPDIR"
+ ;;
+ 2)
+ set_usb_dir() {
+ while true; do
+ comp_box "$SETBOOT_SELECT_INSTALL_DIR"
+ du -hL /mnt |
+ awk '{print NR") "$2" ($SETBOOT_SPACE_USED$1")"}' |
+ while IFS= read -r line; do
+ content_line "$line"
+ done
+ content_line ""
+ content_line "0) $COMMON_BACK"
+ separator_line "="
+ read -r -p "$COMMON_INPUT> " num
+ BINDIR=$(du -hL /mnt | awk '{print $2}' | sed -n "$num"p)
+ if [ "$num" = 0 ]; then
+ return 1
+ elif [ -z "$BINDIR" ]; then
+ msg_alert "\033[31m$SETBOOT_INPUT_ERROR\033[0m"
+ else
+ return 0
+ fi
+ done
+ }
+ set_usb_dir
+ if [ $? -eq 1 ]; then
+ continue
fi
- }
- set_usb_dir
- ;;
- 3)
- input_dir() {
- read -p "请输入自定义目录 > " BINDIR
- if [ ! -d "$BINDIR" ]; then
- echo "\033[31m输入错误!请重新设置!\033[0m"
- input_dir
+ ;;
+ 3)
+ input_dir() {
+ while true; do
+ comp_box "\033[36m$SETBOOT_INPUT_CMD\033[0m" \
+ "$SETBOOT_INPUT_OR_BACK"
+ read -r -p "$SETBOOT_INPUT> " BINDIR
+ if [ "$BINDIR" = 0 ]; then
+ return 1
+ elif [ ! -d "$BINDIR" ]; then
+ msg_alert "\033[31m$SETBOOT_INPUT_ERROR\033[0m"
+ fi
+ return 0
+ done
+ }
+ input_dir
+ if [ $? -eq 1 ]; then
+ continue
fi
- }
- input_dir
- ;;
- *)
- errornum
- ;;
- esac
- setconfig BINDIR "$BINDIR" "$CRASHDIR"/configs/command.env
+ ;;
+ *)
+ errornum
+ continue
+ ;;
+ esac
+ sed -i "s#BINDIR=.*#BINDIR=$BINDIR#" "$CRASHDIR"/configs/command.env
+ break
+ done
;;
6)
- echo -e "\033[33m如果你的设备启动后可以正常使用,则无需变更设置!!\033[0m"
- echo -e "\033[36m禁用时,如果使用了小闪存模式或者rule-set等在线规则,则可能会因无法联网而导致启动失败!\033[0m"
- echo -e "\033[32m启用时,会导致部分性能较差或者拨号较慢的设备可能会因查询超时导致启动失败!\033[0m"
- read -p "是否切换?(1/0) > " res
- [ "$res" = '1' ] && {
+ comp_box "\033[33m$SETBOOT_NETCHK_HINT1\033[0m" \
+ "\033[36m$SETBOOT_NETCHK_HINT2\033[0m" \
+ "\033[32m$SETBOOT_NETCHK_HINT3\033[0m"
+
+ if [ "$network_check" = "OFF" ]; then
+ content_line "$SETBOOT_NETCHK_OFF_CONFIRM"
+ else
+ content_line "$SETBOOT_NETCHK_ON_CONFIRM"
+ fi
+ separator_line "-"
+ btm_box "1) $SETBOOT_YES" \
+ "0) $SETBOOT_NO_BACK"
+ read -r -p "$COMMON_INPUT> " res
+ if [ "$res" = '1' ]; then
if [ "$network_check" = "OFF" ]; then
network_check=ON
else
network_check=OFF
fi
- setconfig network_check "$network_check"
- }
- sleep 1
+ if setconfig network_check "$network_check"; then
+ common_success
+ else
+ common_failed
+ fi
+ fi
+ ;;
+ 7)
+ if [ -s "$TMPDIR"/ShellCrash.log ]; then
+ line_break
+ echo "==========================================================="
+ grep -v "$SETBOOT_TASK_WORD" "$TMPDIR"/ShellCrash.log
+ echo "==========================================================="
+ line_break
+ exit
+ else
+ msg_alert "\033[31m$SETBOOT_LOG_NOT_FOUND\033[0m"
+ fi
;;
*)
errornum
- sleep 1
- break
;;
esac
done
diff --git a/scripts/menus/5_task.sh b/scripts/menus/5_task.sh
index 5886de0a..5fb7f363 100644
--- a/scripts/menus/5_task.sh
+++ b/scripts/menus/5_task.sh
@@ -4,341 +4,384 @@
[ -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
- echo "-----------------------------------------------"
- echo -e "\033[33m$cron_time\033[0m执行任务:\033[36m$task_name\033[0m"
- read -p "是否确认添加定时任务?(1/0) > " 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"
- echo -e "任务【$cron_time$task_name】\033[32m已添加!\033[0m"
- 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
- echo -e "任务【$3】\033[32m添加成功!\033[0m"
- sleep 1
-}
-#任务界面
-task_user_add(){ #自定义命令添加
- echo "-----------------------------------------------"
- echo -e "\033[33m命令可包含空格,请确保命令可执行!\033[0m"
- echo -e "\033[36m此处不要添加执行条件,请在添加完成后返回添加具体执行条件!\033[0m"
- echo -e "也可以手动编辑\033[32m${CRASHDIR}/task/task.user\033[0m添加"
- read -p "请输入命令语句 > " script
- if [ -n "$script" ];then
- task_command=$script
- echo -e "请检查输入:\033[32m$task_command\033[0m"
- #获取本任务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 -p "请输入任务备注 > " txt
- [ -n "$txt" ] && task_name=$txt || task_name=自定义任务$task_id
- echo "$task_id#$task_command#$task_name" >> "$CRASHDIR"/task/task.user
- echo -e "\033[32m自定义任务已添加!\033[0m"
- sleep 1
- else
- echo -e "\033[31m输入错误,请重新输入!\033[0m"
- sleep 1
- fi
-}
-task_user_del(){ #自定义命令删除
- echo "-----------------------------------------------"
- echo -e "请输入对应ID移除对应自定义任务(不会影响内置任务)"
- echo -e "也可以手动编辑\033[32m${CRASHDIR}/task/task.user\033[0m"
- echo "-----------------------------------------------"
- cat "$CRASHDIR"/task/task.user 2>/dev/null | grep -Ev '^#' | awk -F '#' '{print $1" "$3}'
- echo "-----------------------------------------------"
- echo "0 返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- if [ -n "$num" ];then
- sed -i "/^$num#/d" "$CRASHDIR"/task/task.user 2>/dev/null
- [ "$num" != 0 ] && task_user_del
- else
- echo -e "\033[31m输入错误,请重新输入!\033[0m"
- sleep 1
- fi
-}
-task_add(){ #任务添加
- echo "-----------------------------------------------"
- echo -e "\033[36m请选择需要添加的任务\033[0m"
- echo "-----------------------------------------------"
- #输出任务列表
- cat "$CRASHDIR"/task/task.list "$CRASHDIR"/task/task.user 2>/dev/null | grep -Ev '^(#|$)' | awk -F '#' '{print " "NR" "$3}'
- echo "-----------------------------------------------"
- echo -e " 0 返回上级菜单"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0)
- ;;
- [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
- else
- errornum
- fi
- ;;
- *)
- errornum
- ;;
- esac
-}
-task_del(){ #任务删除
- #删除定时任务
- cronset "$1"
- #删除条件任务
- 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(){ #任务条件选择菜单
- echo "-----------------------------------------------"
- echo -e "请选择任务\033[36m【$task_name】\033[0m执行条件:"
- echo "-----------------------------------------------"
- echo -e " 1 定时任务\033[32m每周执行\033[0m"
- echo -e " 2 定时任务\033[32m每日执行\033[0m"
- echo -e " 3 定时任务\033[32m每小时执行\033[0m"
- echo -e " 4 定时任务\033[32m每分钟执行\033[0m"
- echo "-----------------------------------------------"
- echo -e "\033[31m注意:\033[0m逻辑水平不及格的请勿使用下方触发条件!"
- echo "-----------------------------------------------"
- echo -e " 5 服务\033[33m启动前执行\033[0m"
- echo -e " 6 服务\033[33m启动后执行\033[0m"
- echo -e " 7 服务\033[33m运行时每分钟执行\033[0m"
- echo -e " 8 防火墙服务\033[33m重启后执行\033[0m"
- echo "-----------------------------------------------"
- echo -e " 0 返回上级菜单"
- read -p "请输入对应数字 > " num
- case "$num" in
+[ -z "$TASKCFGDIR" ] && TASKCFGDIR="$CRASHDIR"/configs/task
- 0)
- return 1
- ;;
- 1)
- echo "-----------------------------------------------"
- echo -e " 输入 1-7 对应\033[33m每周的指定某天\033[0m运行(7=周日)"
- echo -e " 输入 1,4,0 代表\033[36m每周一、周四、周日\033[0m运行"
- echo -e " 输入 1-5 代表\033[36m周一至周五\033[0m运行"
- read -p "在每周哪天执行? > " week
- week=`echo ${week/7/0}` #把7换成0
- echo "-----------------------------------------------"
- read -p "想在该日的具体哪个小时执行?(0-23) > " hour
- cron_time="在每周$week的$hour点整"
- cron_time=`echo ${cron_time/周0/周日}` #把0换成日
- [ -n "$week" ] && [ -n "$hour" ] && set_cron
- ;;
- 2)
- echo "-----------------------------------------------"
- echo -e " 输入 1,7,15 代表\033[36m每到1,7,15点\033[0m运行"
- echo -e " 输入 6-18 代表\033[36m早6点至晚18点间每小时\033[0m运行"
- read -p "想在每日的具体哪个小时执行?(0-23) > " hour
- echo "-----------------------------------------------"
- read -p "想在具体哪分钟执行?(0-59的整数) > " min
- cron_time="在每日的$hour点$min分"
- [ -n "$min" ] && [ -n "$hour" ] && set_cron
- ;;
- 3)
- echo "-----------------------------------------------"
- read -p "想每隔多少小时执行一次?(1-23的整数) > " num
- hour="*/$num"
- cron_time="每隔$num小时"
- [ -n "$hour" ] && set_cron
- ;;
- 4)
- echo "-----------------------------------------------"
- read -p "想每隔多少分钟执行一次?(1-59的整数) > " 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)
- echo "-----------------------------------------------"
- echo -e " 输入10即每隔10分钟运行一次,1440即每隔24小时运行一次"
- echo -e " 大于60分钟的数值将按小时取整,且按当前时区记时"
- read -p "想每隔多少分钟执行一次?(1-1440的整数) > " 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)
- echo -e "该功能会将相关启动代码注入到/etc/init.d/firewall中"
- read -p "是否继续?(1/0) > " res
- [ "$res" = 1 ] && set_service affirewall "$task_id" "防火墙重启后$task_name"
- ;;
- *)
- errornum
- return 1
- ;;
- esac
-}
-task_manager(){ #任务管理列表
- echo "-----------------------------------------------"
- #抽取并生成临时列表
- cronload > "$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
- echo -e "\033[31m当前没有可供管理的任务!\033[36m"
- sleep 1
- else
- echo -e "\033[33m已添加的任务:\033[0m"
- echo "-----------------------------------------------"
- cat "$TMPDIR"/task_list | awk '{print " " NR " " $2}'
- echo "-----------------------------------------------"
- echo -e " a 清空旧版任务"
- echo -e " d 清空任务列表"
- echo -e " 0 返回上级菜单"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0)
- ;;
- a)
- task_del "#"
- echo -e "\033[31m旧版任务已清空!\033[36m"
- sleep 1
- ;;
- d)
- task_del "task.sh"
- echo -e "\033[31m全部任务已清空!\033[36m"
- sleep 1
- ;;
- [1-9]|[1-9][0-9])
+load_lang 5_task
- task_txt=$(sed -n "$num p" "$TMPDIR"/task_list)
- task_id=$(echo $task_txt | awk '{print $1}')
- if [ "$task_id" = 0 ];then
- read -p "旧版任务不支持管理,是否移除?(1/0) > " res
- [ "$res" = 1 ] && {
- cronname=$(echo $task_txt | awk -F '-' '{print $2}')
- cronset "$cronname"
- sed -i "/$cronname/d" "$CRASHDIR"/task/cron 2>/dev/null
- }
- 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}')
- echo "-----------------------------------------------"
- echo -e "当前任务为:\033[36m $task_des\033[0m"
- echo -e " 1 \033[33m修改\033[0m当前任务"
- echo -e " 2 \033[31m删除\033[0m当前任务"
- echo -e " 3 \033[32m立即执行\033[0m一次"
- echo -e " 4 查看\033[33m执行记录\033[0m"
- echo "-----------------------------------------------"
- echo -e " 0 返回上级菜单"
- read -p "请选择需要执行的操作 > " num
- case "$num" in
- 0)
- ;;
- 1)
- task_type && task_del $task_des
- ;;
- 2)
- task_del $task_des
- ;;
- 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='执行失败!'
- echo -e "\033[33m任务【$task_des】$task_res\033[0m"
- sleep 1
- ;;
- 4)
- echo "-----------------------------------------------"
- if [ -n "$(cat "$TMPDIR"/ShellCrash.log | grep "$task_name")" ];then
- cat "$TMPDIR"/ShellCrash.log | grep "$task_name"
- else
- echo -e "\033[31m未找到相关执行记录!\033[0m"
- fi
- sleep 1
- ;;
- *)
- errornum
- ;;
- esac
- fi
- task_manager
- ;;
- *)
- errornum
- ;;
- esac
- fi
+# 任务工具
+set_cron() {
+ [ -z "$week" ] && week=*
+ [ -z "$hour" ] && hour=*
+ [ -z "$min" ] && min=0
+ comp_box "\033[33m$cron_time\033[0m$TASK5_RUN_TASK\033[36m$task_name\033[0m" \
+ "" \
+ "$TASK5_CONFIRM_ADD_CRON"
+ btm_box "1) $TASK5_YES" \
+ "0) $TASK5_NO"
+ read -r -p "$COMMON_INPUT> " 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"
+ msg_alert -t 0 "$TASK5_TASK_PREFIX$cron_time$task_name$TASK5_TASK_ADDED"
+ fi
+ unset week hour min
+ sleep 1
}
-task_recom(){ #任务推荐
- echo "-----------------------------------------------"
- echo -e "\033[32m启用推荐的自动任务配置?这包括:\033[0m"
- echo "-----------------------------------------------"
- echo -e "每隔10分钟自动保存面板配置"
- echo -e "服务启动后自动同步ntp时间"
- echo -e "在每日的3点0分重启服务"
- echo "-----------------------------------------------"
- read -p "是否启用?(1/0) > " res
- [ "$res" = 1 ] && {
- set_service running "106" "运行时每10分钟自动保存面板配置" "*/10 * * * *"
- set_service afstart "107" "服务启动后自动同步ntp时间"
- cronset "在每日的3点0分重启服务" "0 3 * * * ${CRASHDIR}/task/task.sh 103 在每日的3点0分重启服务" && \
- echo -e "任务【在每日的3点0分重启服务】\033[32m添加成功!\033[0m"
- }
+
+set_service() {
+ # 参数1代表要任务类型,参数2代表任务ID,参数3代表任务描述,参数4代表running任务cron时间
+ mkdir -p "$TASKCFGDIR"
+ task_file="$TASKCFGDIR"/$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$COMMON_SUCCESS\033[0m"
+ sleep 1
+}
+
+# 任务界面
+#
+# 自定义命令添加
+task_user_add() {
+ while true; do
+ comp_box "\033[33m$TASK5_USER_ADD_HINT1\033[0m" \
+ "\033[36m$TASK5_USER_ADD_HINT2\033[0m" \
+ "$TASK5_USER_ADD_HINT3\033[32m${TASKCFGDIR}/task.user\033[0m$TASK5_USER_ADD_HINT4"
+ btm_box "\033[36m$TASK5_INPUT_CMD\033[0m" \
+ "$TASK5_OR_BACK"
+ read -r -p "$TASK5_INPUT> " script
+ if [ "$script" = 0 ]; then
+ break
+ elif [ -n "$script" ]; then
+ task_command=$script
+ comp_box "$TASK5_CHECK_INPUT\033[32m$task_command\033[0m"
+ # 获取本任务ID
+ task_max_id=$(awk -F '#' '{print $1}' "$TASKCFGDIR"/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 "$TASK5_INPUT_REMARK> " txt
+ [ -n "$txt" ] && task_name=$txt || task_name="$TASK5_CUSTOM_TASK$task_id"
+ echo "$task_id#$task_command#$task_name" >>"$TASKCFGDIR"/task.user
+ msg_alert "\033[32m$TASK5_CUSTOM_ADDED\033[0m"
+ break
+ else
+ msg_alert "\033[31m$TASK5_INPUT_ERROR\033[0m"
+ fi
+ done
+}
+
+# 自定义命令删除
+task_user_del() {
+ while true; do
+ if grep -Evq '^#' "$TASKCFGDIR/task.user" 2>/dev/null; then
+ comp_box "$TASK5_USER_DEL_HINT1" \
+ "$TASK5_USER_DEL_HINT2\033[32m${TASKCFGDIR}/task.user\033[0m"
+ grep -Ev '^#' "$TASKCFGDIR/task.user" 2>/dev/null |
+ awk -F '#' '{print $1") "$3}' |
+ while IFS= read -r line; do
+ content_line "$line"
+ done
+ btm_box "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ if [ "$num" = 0 ]; then
+ break
+ elif [ -n "$num" ]; then
+ sed -i "/^$num#/d" "$TASKCFGDIR"/task.user 2>/dev/null
+ common_success
+ else
+ msg_alert "\033[31m$TASK5_INPUT_ERROR\033[0m"
+ fi
+ else
+ msg_alert "\033[33m$TASK5_NO_CUSTOM_TASK\033[0m"
+ break
+ fi
+ done
+}
+
+# 任务添加
+task_add() {
+ while true; do
+ comp_box "\033[36m$TASK5_SELECT_ADD\033[0m"
+ # 输出任务列表
+ list=$(cat "$CRASHDIR"/task/task_${i18n}.list "$TASKCFGDIR"/task.user 2>/dev/null | grep -Ev '^(#|$)' | awk -F '#' '{print $3}')
+ list_box "$list"
+ btm_box "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ 0)
+ break
+ ;;
+ [1-9] | [1-9][0-9])
+ if [ "$num" -le "$(echo "$list" | wc -l)" ]; then
+ task_id=$(cat "$CRASHDIR"/task/task_${i18n}.list "$TASKCFGDIR"/task.user 2>/dev/null | grep -Ev '^(#|$)' | sed -n "$num p" | awk -F '#' '{print $1}')
+ task_name=$(cat "$CRASHDIR"/task/task_${i18n}.list "$TASKCFGDIR"/task.user 2>/dev/null | grep -Ev '^(#|$)' | sed -n "$num p" | awk -F '#' '{print $3}')
+ task_type
+ break
+ else
+ errornum
+ fi
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
+}
+
+# 任务删除
+task_del() {
+ # 删除定时任务
+ cronset "$1"
+ # 删除条件任务
+ sed -i "/$1/d" "$TASKCFGDIR"/cron 2>/dev/null
+ sed -i "/$1/d" "$TASKCFGDIR"/bfstart 2>/dev/null
+ sed -i "/$1/d" "$TASKCFGDIR"/afstart 2>/dev/null
+ sed -i "/$1/d" "$TASKCFGDIR"/running 2>/dev/null
+ sed -i "/$1/d" "$TASKCFGDIR"/affirewall 2>/dev/null
+}
+
+# 任务条件选择菜单
+task_type() {
+ comp_box "$TASK5_SELECT_COND\033[36m【$task_name】\033[0m$TASK5_SELECT_COND2"
+ btm_box "1) $TASK5_COND_1" \
+ "2) $TASK5_COND_2" \
+ "3) $TASK5_COND_3" \
+ "4) $TASK5_COND_4" \
+ "$TASK5_WARN_LINE1" \
+ "$TASK5_WARN_LINE2" \
+ "$TASK5_WARN_LINE3" \
+ "5) $TASK5_COND_5" \
+ "6) $TASK5_COND_6" \
+ "7) $TASK5_COND_7" \
+ "8) $TASK5_COND_8" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ 0)
+ return 1
+ ;;
+ 1)
+
+ comp_box "$TASK5_WEEK_HINT1" \
+ "$TASK5_WEEK_HINT2" \
+ "$TASK5_WEEK_HINT3"
+ read -r -p "$TASK5_WEEK_INPUT> " week
+ # week=`echo ${week/7/0}` # 把7换成0
+ read -r -p "$TASK5_HOUR_INPUT1> " hour
+ cron_time="$TASK5_CRON_WEEK$week$TASK5_CRON_WEEK2$hour$TASK5_OCLOCK"
+ # cron_time=`echo ${cron_time/周0/周日}` # 把0换成日
+ [ -n "$week" ] && [ -n "$hour" ] && set_cron
+ ;;
+ 2)
+ comp_box "$TASK5_DAY_HINT1" \
+ "$TASK5_DAY_HINT2"
+ read -r -p "$TASK5_HOUR_INPUT2> " hour
+ read -r -p "$TASK5_MIN_INPUT> " min
+ cron_time="$TASK5_CRON_DAY$hour$TASK5_POINT$min$TASK5_MINUTE"
+ [ -n "$min" ] && [ -n "$hour" ] && set_cron
+ ;;
+ 3)
+ line_break
+ read -r -p "$TASK5_EVERY_HOUR_INPUT> " num
+ hour="*/$num"
+ cron_time="$TASK5_EVERY$num$TASK5_HOUR"
+ [ -n "$hour" ] && set_cron
+ ;;
+ 4)
+ line_break
+ read -r -p "$TASK5_EVERY_MIN_INPUT> " num
+ min="*/$num"
+ cron_time="$TASK5_EVERY$num$TASK5_MIN"
+ [ -n "$min" ] && set_cron
+ ;;
+ 5)
+ set_service bfstart "$task_id" "$TASK5_BFSTART$task_name"
+ ;;
+ 6)
+ set_service afstart "$task_id" "$TASK5_AFSTART$task_name"
+ ;;
+ 7)
+ comp_box "$TASK5_RUNNING_HINT1" \
+ "$TASK5_RUNNING_HINT2"
+ read -r -p "$TASK5_RUNNING_INPUT> " num
+ if [ "$num" -lt 60 ]; then
+ min="$num"
+ cron_time="*/$min * * * *"
+ time_des="$min$TASK5_MIN"
+ else
+ hour="$((num / 60))"
+ cron_time="0 */$hour * * *"
+ time_des="$hour$TASK5_HOUR"
+ fi
+ [ -n "$cron_time" ] && set_service running "$task_id" "$TASK5_RUNNING_PREFIX$time_des$task_name" "$cron_time"
+ ;;
+ 8)
+ comp_box "$TASK5_AFFW_HINT"
+ "$TASK5_CONFIRM_CONTINUE"
+ btm_box "1) $TASK5_YES" \
+ "0) $TASK5_NO"
+ read -r -p "$COMMON_INPUT> " res
+ [ "$res" = 1 ] && set_service affirewall "$task_id" "$TASK5_AFFW_PREFIX$task_name"
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+}
+
+# 任务管理列表
+task_manager() {
+ while true; do
+ # 抽取并生成临时列表
+ cronload >"$TMPDIR"/task_cronlist
+ cat "$TMPDIR"/task_cronlist "$TASKCFGDIR"/running 2>/dev/null | sort -u | grep -oE "task/task.sh .*" | cut -d ' ' -f 2- >"$TMPDIR"/task_list
+ cat "$TASKCFGDIR"/bfstart "$TASKCFGDIR"/afstart "$TASKCFGDIR"/affirewall 2>/dev/null | cut -d ' ' -f 2- >>"$TMPDIR"/task_list
+ cat "$TMPDIR"/task_cronlist 2>/dev/null | sort -u | grep -oE " #.*" | grep -v "$TASK5_GUARD_WORD" | awk -F '#' '{print "0 '$TASK5_OLD_PREFIX'"$2}' >>"$TMPDIR"/task_list
+ sed -i '/^ *$/d' "$TMPDIR"/task_list
+ rm -rf "$TMPDIR"/task_cronlist
+ # 判断为空则返回
+ if [ ! -s "$TMPDIR"/task_list ]; then
+ msg_alert "\033[31m$TASK5_NONE_TO_MANAGE\033[36m"
+ break
+ else
+ comp_box "\033[33m$TASK5_ADDED_TASKS\033[0m"
+ list_box "$(cat "$TMPDIR"/task_list)"
+ separator_line "-"
+ btm_box "a) $TASK5_CLEAR_OLD" \
+ "d) $TASK5_CLEAR_ALL" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ a)
+ task_del "#"
+ msg_alert "\033[31m$TASK5_OLD_CLEARED\033[36m"
+ ;;
+ d)
+ task_del "task.sh"
+ msg_alert "\033[31m$TASK5_ALL_CLEARED\033[36m"
+ ;;
+ [1-9] | [1-9][0-9])
+ task_txt=$(sed -n "$num p" "$TMPDIR"/task_list)
+ task_id=$(echo "$task_txt" | awk '{print $1}')
+
+ if [ "$task_id" = 0 ]; then
+ comp_box "$TASK5_OLD_NOT_SUPPORT"
+ btm_box "1) $TASK5_YES" \
+ "0) $TASK5_NO_BACK"
+ read -r -p "$COMMON_INPUT> " res
+ if [ "$res" = 1 ]; then
+ cronname=$(echo "$task_txt" | awk -F '-' '{print $2}')
+ cronset "$cronname"
+ sed -i "/$cronname/d" "$TASKCFGDIR"/cron 2>/dev/null
+
+ break
+ fi
+ else
+ task_des=$(echo "$task_txt" | awk '{print $2}')
+ task_name=$(cat "$CRASHDIR"/task/task_${i18n}.list "$TASKCFGDIR"/task.user 2>/dev/null | grep "$task_id" | awk -F '#' '{print $3}')
+ comp_box "$TASK5_CURRENT_TASK\033[36m$task_des\033[0m"
+ btm_box "1) $TASK5_EDIT_TASK" \
+ "2) $TASK5_DEL_TASK" \
+ "3) $TASK5_RUN_ONCE" \
+ "4) $TASK5_VIEW_RECORD" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 0)
+ continue
+ ;;
+ 1)
+ task_type && task_del "$task_des"
+ ;;
+ 2)
+ task_del "$task_des"
+ common_success
+ ;;
+ 3)
+ task_command=$(cat "$CRASHDIR"/task/task_${i18n}.list "$TASKCFGDIR"/task.user 2>/dev/null | grep "$task_id" | awk -F '#' '{print $2}')
+ eval "$task_command" && task_res="$TASK5_RUN_OK" || task_res="$TASK5_RUN_FAIL"
+ msg_alert "\033[33m$TASK5_TASK_PREFIX$task_des】$task_res\033[0m"
+ ;;
+ 4)
+ if cat "$TMPDIR"/ShellCrash.log | grep -q "$task_name"; then
+ line_break
+ echo "==========================================================="
+ cat "$TMPDIR"/ShellCrash.log | grep "$task_name"
+ echo "==========================================================="
+ else
+ msg_alert "\033[31m$TASK5_RECORD_NOT_FOUND\033[0m"
+ fi
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ fi
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ fi
+ done
+}
+
+# 任务推荐
+task_recom() {
+ comp_box "\033[36m$TASK_RECOM_TITLE\033[0m" \
+ "" \
+ "$TASK_RECOM_ITEM_1" \
+ "$TASK_RECOM_ITEM_2" \
+ "$TASK_RECOM_ITEM_3"
+ btm_box "1) $TASK5_YES" \
+ "0) $TASK5_NO"
+ read -r -p "$COMMON_INPUT>" res
+
+ [ "$res" = 1 ] && {
+ line_break
+ separator_line "="
+ set_service running "106" "$TASK_RECOM_ITEM_1" "*/10 * * * *"
+ set_service afstart "107" "$TASK_RECOM_ITEM_2"
+ cronset "$TASK_RECOM_ITEM_3" "0 3 * * * ${CRASHDIR}/task/task.sh 103 $TASK_RECOM_ITEM_3" &&
+ content_line "【$TASK_RECOM_ITEM_3】\033[32m$COMMON_SUCCESS\033[0m"
+ separator_line "="
+ }
}
# 任务菜单
task_menu() {
while true; do
- #检测并创建自定义任务文件
- [ -f "$CRASHDIR"/task/task.user ] || echo '#任务ID(必须>200并顺序排列)#任务命令#任务说明(#号隔开,任务命令和说明中都不允许包含#号)' >"$CRASHDIR"/task/task.user
- echo "-----------------------------------------------"
- echo -e "\033[30;47m欢迎使用自动任务功能:\033[0m"
- echo "-----------------------------------------------"
- echo -e " 1 添加\033[32m自动任务\033[0m"
- echo -e " 2 管理\033[33m任务列表\033[0m"
- echo -e " 3 查看\033[36m任务日志\033[0m"
- echo -e " 4 配置\033[36m日志推送\033[0m"
- echo -e " 5 添加\033[33m自定义任务\033[0m"
- echo -e " 6 删除\033[33m自定义任务\033[0m"
- echo -e " 7 使用\033[32m推荐设置\033[0m"
- echo "-----------------------------------------------"
- echo -e " 0 返回上级菜单"
- read -p "请输入对应数字 > " num
+ # 检测并创建自定义任务文件
+ mkdir -p "$TASKCFGDIR"
+ [ -f "$TASKCFGDIR"/task.user ] || echo "$TASK5_USER_FILE_HEADER" >"$TASKCFGDIR"/task.user
+ comp_box "\033[30;47m$TASK5_MENU_TITLE\033[0m"
+ btm_box "1) $TASK5_MENU_1" \
+ "2) $TASK5_MENU_2" \
+ "3) $TASK5_MENU_3" \
+ "4) $TASK5_MENU_4" \
+ "5) $TASK5_MENU_5" \
+ "6) $TASK5_MENU_6" \
+ "7) $TASK5_MENU_7" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
case "$num" in
"" | 0)
break
@@ -351,17 +394,17 @@ task_menu() {
rm -rf "$TMPDIR"/task_list
;;
3)
- if [ -n "$(cat "$TMPDIR"/ShellCrash.log | grep '任务【')" ]; then
- echo "-----------------------------------------------"
- cat "$TMPDIR"/ShellCrash.log | grep '任务【'
+ if cat "$TMPDIR"/ShellCrash.log | grep -q "$TASK5_TASK_GREP"; then
+ line_break
+ echo "==========================================================="
+ cat "$TMPDIR"/ShellCrash.log | grep "$TASK5_TASK_GREP"
+ echo "==========================================================="
else
- echo -e "\033[31m未找到任务相关执行日志!\033[0m"
+ msg_alert "\033[31m$TASK5_LOG_NOT_FOUND\033[0m"
fi
- sleep 1
;;
4)
- echo "-----------------------------------------------"
- echo -e "\033[36m请在日志工具中配置相关推送通道及推送开关\033[0m"
+ msg_alert "\033[36m$TASK5_PUSH_HINT\033[0m"
. "$CRASHDIR"/menus/8_tools.sh && log_pusher
;;
5)
@@ -375,8 +418,6 @@ task_menu() {
;;
*)
errornum
- sleep 1
- break
;;
esac
done
diff --git a/scripts/menus/6_core_config.sh b/scripts/menus/6_core_config.sh
index 6f9fbc7f..8be1b22f 100644
--- a/scripts/menus/6_core_config.sh
+++ b/scripts/menus/6_core_config.sh
@@ -4,1188 +4,489 @@
[ -n "$__IS_MODULE_6_CORECONFIG_LOADED" ] && return
__IS_MODULE_6_CORECONFIG_LOADED=1
-YAMLSDIR="$CRASHDIR"/yamls
-JSONSDIR="$CRASHDIR"/jsons
+load_lang 6_core_config
-#导入订阅、配置文件相关
-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
- else
- rule_type_set=$(echo $rule_type|cut -d' ' -f$num)
- echo "-----------------------------------------------"
- echo -e "\033[33m请输入规则语句,可以是域名、泛域名、IP网段或者其他匹配规则类型的内容\033[0m"
- read -p "请输入对应规则 > " rule_state_set
- [ -n "$rule_state_set" ] && set_group_type || errornum
- fi
- ;;
- *)
- errornum
- ;;
- 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
- else
- rule_group_set=$(echo $rule_group|cut -d'#' -f$num)
- rule_all="- ${rule_type_set},${rule_state_set},${rule_group_set}"
- [ -n "$(echo IP-CIDR SRC-IP-CIDR IP-CIDR6|grep "$rule_type_set")" ] && rule_all="${rule_all},no-resolve"
- echo "$rule_all" >> "$YAMLSDIR"/rules.yaml
- echo "-----------------------------------------------"
- echo -e "\033[32m添加成功!\033[0m"
- fi
- ;;
- *)
- errornum
- ;;
- esac
- }
- del_rule_type(){
- 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) ;;
- '') ;;
- *)
- if [ "$num" -le "$(wc -l < "$YAMLSDIR"/rules.yaml)" ];then
- sed -i "${num}d" "$YAMLSDIR"/rules.yaml
- sleep 1
- del_rule_type
- else
- errornum
- fi
- ;;
- esac
- }
- 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'
- }
- 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)
- ;;
- 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
- setrules
- ;;
- 2)
- echo "-----------------------------------------------"
- if [ -s "$YAMLSDIR"/rules.yaml ];then
- del_rule_type
- else
- echo -e "请先添加自定义规则!"
- sleep 1
- fi
- setrules
- ;;
- 3)
- read -p "确认清空全部自定义规则?(1/0) > " res
- [ "$res" = "1" ] && sed -i '/^\s*[^#]/d' "$YAMLSDIR"/rules.yaml
- setrules
- ;;
- 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
- setrules
- ;;
- *)
- errornum
- ;;
- esac
-}
-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 -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 -p "请输入对应数字 > " num
- new_group_type=$(echo $group_type | awk '{print $'"$num"'}')
- if [ "$num" = "1" ];then
- unset new_group_url interval
- else
- read -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 < " 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
- fi
- ;;
- esac
- }
- 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 -p "请输入对应数字 > " num
- case "$num" in
- 0)
- ;;
- 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
- setgroups
- ;;
- 2)
- echo "-----------------------------------------------"
- cat "$YAMLSDIR"/proxy-groups.yaml
- setgroups
- ;;
- 3)
- read -p "确认清空全部自定义策略组?(1/0) > " res
- [ "$res" = "1" ] && echo '#用于添加自定义策略组' > "$YAMLSDIR"/proxy-groups.yaml
- setgroups
- ;;
- *)
- errornum
- ;;
- esac
-}
-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 -p "请输入节点 > " proxy_state_set
- if [ -n "$(echo $proxy_state_set | grep "#" )" ];then
- echo -e "\033[33m绝对禁止包含【#】号!!!\033[0m"
- elif [ -n "$(echo $proxy_state_set | grep -E "^name:" )" ];then
- set_group_add
- else
- errornum
- 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 -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
- fi
- ;;
- esac
- }
- 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 -p "请输入对应数字 > " num
- case "$num" in
- 0)
- ;;
- 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
- setproxies
- ;;
- 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 -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
- setproxies
- ;;
- 3)
- read -p "确认清空全部自定义节点?(1/0) > " res
- [ "$res" = "1" ] && sed -i '/^\s*[^#]/d' "$YAMLSDIR"/proxies.yaml 2>/dev/null
- setproxies
- ;;
- 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
- setrules
- ;;
- *)
- errornum
- ;;
- esac
-}
-gen_clash_providers(){ #生成clash的providers配置文件
- gen_clash_providers_txt(){
- if [ -n "$(echo $2|grep -E '^./')" ];then
- local type=file
- local path=$2
- local download_url=
- else
- local type=http
- local path="./providers/${1}.yaml"
- local download_url=$2
- fi
- cat >> $TMPDIR/providers/providers.yaml <> $TMPDIR/providers/providers.yaml < "$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 "$2" ];then
- gen_clash_providers_txt $1 $2
- providers_tags=$1
- echo ' - {name: '${1}', type: url-test, tolerance: 100, lazy: true, use: ['${1}']}' >> "$TMPDIR"/providers/proxy-groups.yaml
- else
- providers_tags=''
- while read line;do
- tag=$(echo $line | awk '{print $1}')
- url=$(echo $line | awk '{print $2}')
- providers_tags=$(echo "$providers_tags, $tag" | sed 's/^, //')
- gen_clash_providers_txt $tag $url
- echo ' - {name: '${tag}', type: url-test, tolerance: 100, lazy: true, use: ['${tag}']}' >> "$TMPDIR"/providers/proxy-groups.yaml
- done < "$CRASHDIR"/configs/providers.cfg
- 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 && cronset '更新订阅'
- exit
- }
- else
- rm -rf "$TMPDIR"/CrashCore
- rm -rf "$TMPDIR"/config.yaml
- echo -e "\033[31m生成配置文件出错,请仔细检查输入!\033[0m"
- fi
-}
-gen_singbox_providers(){ #生成singbox的providers配置文件
- gen_singbox_providers_txt(){
- if [ -n "$(echo $2|grep -E '^./')" ];then
- cat >> "$TMPDIR"/providers/providers.json <> "$TMPDIR"/providers/providers.json <> "$TMPDIR"/providers/providers.json < "$TMPDIR"/providers/providers.json < "$TMPDIR"/providers/outbounds_add.json <> "$TMPDIR"/providers/outbounds_add.json
- else
- providers_tags=''
- while read line;do
- tag=$(echo $line | awk '{print $1}')
- url=$(echo $line | awk '{print $2}')
- providers_tags=$(echo "$providers_tags, \"$tag\"" | sed 's/^, //')
- gen_singbox_providers_txt $tag $url
- echo '{ "tag": "'${tag}'", "type": "urltest", "tolerance": 100, "providers": ["'${tag}'"], "include": ".*" },' >> "$TMPDIR"/providers/outbounds_add.json
- done < "$CRASHDIR"/configs/providers.cfg
- 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 && cronset '更新订阅'
- exit
- }
- else
- echo -e "\033[31m生成配置文件出错,请仔细检查输入!\033[0m"
- rm -rf "$TMPDIR"/CrashCore
- rm -rf "$TMPDIR"/providers
- fi
-}
-setproviders(){ #自定义providers
- . "$CRASHDIR"/libs/set_cron.sh
- . "$CRASHDIR"/libs/web_get_bin.sh
- #获取模版名称
- if [ -z "$(grep "provider_temp_${coretype}" "$CRASHDIR"/configs/ShellCrash.cfg)" ];then
- provider_temp_des=$(sed -n "1 p" "$CRASHDIR"/configs/${coretype}_providers.list | awk '{print $1}')
- else
- provider_temp_file=$(grep "provider_temp_${coretype}" "$CRASHDIR"/configs/ShellCrash.cfg | awk -F '=' '{print $2}')
- provider_temp_des=$(grep "$provider_temp_file" "$CRASHDIR"/configs/${coretype}_providers.list | awk '{print $1}')
- [ -z "$provider_temp_des" ] && provider_temp_des=$provider_temp_file
- fi
- echo "-----------------------------------------------"
- echo -e "\033[33m你可以在这里快捷管理与生成自定义的providers服务商\033[0m"
- echo -e "\033[33m支持在线及本地的Yaml格式配置导入\033[0m"
- [ -s "$CRASHDIR"/configs/providers.cfg ] && {
- echo "-----------------------------------------------"
- echo -e "\033[36m输入对应数字可管理providers服务商\033[0m"
- cat "$CRASHDIR"/configs/providers.cfg | awk -F "#" '{print " "NR" "$1" "$2}'
- }
- echo -e " d \033[31m清空\033[0mproviders服务商列表"
- echo -e " e \033[33m清理\033[0mproviders目录文件"
- echo "-----------------------------------------------"
- echo -e "\033[36m按照a-b-c的顺序即可完成配置生成\033[0m"
- echo -e " a \033[36m添加\033[0mproviders服务商/节点"
- echo -e " b 选择\033[33m规则模版\033[0m \033[32m$provider_temp_des\033[0m"
- echo -e " c \033[32m生成\033[0m基于providers的配置文件"
- echo "-----------------------------------------------"
- echo -e " 0 返回上级菜单"
- read -p "请输入对应字母或数字 > " num
- case "$num" in
- 0)
- ;;
- [1-9]|[1-9][0-9])
- provider_name=$(sed -n "$num p" "$CRASHDIR"/configs/providers.cfg | awk '{print $1}')
- provider_url=$(sed -n "$num p" "$CRASHDIR"/configs/providers.cfg | awk '{print $2}')
- if [ -z "$provider_name" ];then
- errornum
- else
- echo "-----------------------------------------------"
- echo -e " 1 修改名称:\033[36m$provider_name\033[0m"
- echo -e " 2 修改链接地址:\033[32m$provider_url\033[0m"
- echo -e " 3 生成\033[33m仅包含此链接\033[0m的配置文件"
- echo -e " 4 \033[31m移除此链接\033[0m"
- echo "-----------------------------------------------"
- echo -e " 0 返回上级菜单"
- read -p "请选择需要执行的操作 > " num
- case "$num" in
- 0)
- ;;
- 1)
- read -p "请输入名称或者代号(不可重复,不支持纯数字) > " name
- if [ -n "$name" ] && [ -z "$(echo "$name" | grep -E '^[0-9]+$')" ] && ! grep -q "$name" "$CRASHDIR"/configs/providers.cfg;then
- sed -i "s|$provider_name $provider_url|$name $provider_url|" "$CRASHDIR"/configs/providers.cfg
- else
- echo -e "\033[31m输入错误,请重新输入!\033[0m"
- fi
- ;;
- 2)
- read -p "请输入链接地址或本地相对路径 > " link
- if [ -n "$(echo $link | grep -E '.*\..*|^\./')" ] && [ -z "$(grep "$link" "$CRASHDIR"/configs/providers.cfg)" ];then
- link=$(echo $link | sed 's/\&/\\\&/g') #特殊字符添加转义
- sed -i "s|$provider_name $provider_url|$provider_name $link|" "$CRASHDIR"/configs/providers.cfg
- else
- echo -e "\033[31m输入错误,请重新输入!\033[0m"
- fi
- ;;
- 3)
- gen_${coretype}_providers $provider_name $provider_url
- ;;
- 4)
- sed -i "/^$provider_name /d" "$CRASHDIR"/configs/providers.cfg
- ;;
- *)
- errornum
- ;;
- esac
- sleep 1
- fi
- setproviders
- ;;
- a)
- echo "-----------------------------------------------"
- echo -e "支持填写在线的\033[32mYClash订阅地址\033[0m或者\033[32m本地Clash配置文件\033[0m"
- echo -e "本地配置文件请放在\033[32m$CRASHDIR\033[0m目录下,并填写相对路径如【\033[32m./providers/test.yaml\033[0m】"
- echo "-----------------------------------------------"
- read -p "请输入链接地址或本地相对路径 > " link
- link=$(echo $link | sed 's/ //g') #去空格
- [ -n "$(echo $link | grep -E '.*\..*|^\./')" ] && {
- read -p "请输入名称或代号(不可重复,不支持纯数字) > " name
- name=$(echo $name | sed 's/ //g')
- [ -n "$name" ] && [ -z "$(echo "$name" | grep -E '^[0-9]+$')" ] && ! grep -q "$name" "$CRASHDIR"/configs/providers.cfg && {
- echo "-----------------------------------------------"
- echo -e "名称:\033[36m$name\033[0m"
- echo -e "链接地址/路径:\033[32m$link\033[0m"
- read -p "确认添加?(1/0) > " res
- [ "$res" = 1 ] && {
- echo "$name $link" >> "$CRASHDIR"/configs/providers.cfg
- echo -e "\033[32mproviders已添加!\033[0m"
- }
- }
- }
- [ "$?" != 0 ] && echo -e "\033[31m输入错误,操作已取消!\033[0m"
- sleep 1
- setproviders
- ;;
- c)
- echo "-----------------------------------------------"
- if [ -s "$CRASHDIR"/configs/providers.cfg ];then
- echo -e "\033[33msingboxr与mihomo内核的providers配置文件不互通!\033[0m"
- echo "-----------------------------------------------"
- read -p "确认生成${coretype}配置文件?(1/0) > " res
- [ "$res" = "1" ] && {
- gen_${coretype}_providers
- }
- else
- echo -e "\033[31m你还未添加链接或本地配置文件,请先添加!\033[0m"
- sleep 1
- fi
- setproviders
- ;;
- b)
- echo "-----------------------------------------------"
- echo -e "当前规则模版为:\033[32m$provider_temp_des\033[0m"
- echo -e "\033[33m请选择在线模版:\033[0m"
- echo "-----------------------------------------------"
- cat "$CRASHDIR"/configs/${coretype}_providers.list | awk '{print " "NR" "$1}'
- echo "-----------------------------------------------"
- echo -e " a 使用\033[36m本地模版\033[0m"
- echo "-----------------------------------------------"
- read -p "请输入对应字母或数字 > " num
- case "$num" in
- 0)
- ;;
- a)
- read -p "请输入模版的路径(绝对路径) > " dir
- if [ -s $dir ];then
- provider_temp_file=$dir
- setconfig provider_temp_${coretype} $provider_temp_file
- echo -e "\033[32m设置成功!\033[0m"
- else
- echo -e "\033[31m输入错误,找不到对应模版文件!\033[0m"
- fi
- sleep 1
- ;;
- *)
- provider_temp_file=$(sed -n "$num p" "$CRASHDIR"/configs/${coretype}_providers.list 2>/dev/null | awk '{print $2}')
- if [ -z "$provider_temp_file" ];then
- errornum
- else
- setconfig provider_temp_${coretype} $provider_temp_file
- fi
- ;;
- esac
- setproviders
- ;;
- d)
- read -p "确认清空全部链接?(1/0) > " res
- [ "$res" = "1" ] && rm -rf "$CRASHDIR"/configs/providers.cfg
- setproviders
- ;;
- e)
- echo -e "\033[33m将清空 $CRASHDIR/providers 目录下所有内容\033[0m"
- read -p "是否继续?(1/0) > " res
- [ "$res" = "1" ] && rm -rf "$CRASHDIR"/providers
- setproviders
- ;;
- *)
- errornum
- ;;
- esac
+# 配置文件主界面
+set_core_config() {
+ while true; do
+ list=$(cat "$CRASHDIR"/configs/providers.cfg "$CRASHDIR"/configs/providers_uri.cfg 2>/dev/null |
+ LC_ALL=C awk '{
+ f1 = $1
+ f2 = $2
+ gsub(/\360[\200-\277][\200-\277][\200-\277]/,"",f1)
+ if (length(f1) > 12)
+ f1 = substr(f1, 1, 8) ".."
+ if (length(f2) > 30)
+ f2 = substr(f2, 1, 30) "..."
+ printf "%-7s \t%-28s\n", f1, f2
+}')
+ comp_box "\033[30;47m$CORECFG_TITLE\033[0m"
+ [ -n "$list" ] && {
+ content_line "\033[36m$CORECFG_HINT_SELECT_PROVIDER\033[0m"
+ content_line ""
+ list_box "$list"
+ separator_line "-"
+ }
+ btm_box "a) $CORECFG_MENU_A" \
+ "b) $CORECFG_MENU_B" \
+ "c) $CORECFG_MENU_C" \
+ "d) $CORECFG_MENU_D" \
+ "e) $CORECFG_MENU_E" \
+ "" \
+ "0) $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$CORECFG_CORE_ONLY\033[0m"
+ fi
+ else
+ msg_alert "$CORECFG_ADD_PROVIDER_FIRST"
+ fi
+ ;;
+ c)
+ if [ -s "$CRASHDIR"/configs/providers.cfg ] || [ -s "$CRASHDIR"/configs/providers_uri.cfg ]; then
+ . "$CRASHDIR"/menus/subconverter.sh
+ subconverter
+ else
+ msg_alert "$CORECFG_ADD_PROVIDER_FIRST"
+ fi
+ ;;
+ d)
+ comp_box "\033[33m$CORECFG_CLEAR_WARN\033[0m" \
+ "" \
+ "$CORECFG_CLEAR_CONFIRM"
+ btm_box "1) $CORECFG_YES" \
+ "0) $CORECFG_NO_BACK"
+ read -r -p "$COMMON_INPUT> " 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
+ ;;
+ esac
+ done
}
-set_clash_adv(){ #自定义clash高级规则
- [ ! -f "$YAMLSDIR"/user.yaml ] && cat > "$YAMLSDIR"/user.yaml < "$YAMLSDIR"/others.yaml < " num
- case "$num" in
- 0)
- ;;
- 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
- override
- ;;
- 2)
- setrules
- override
- ;;
- 3)
- setproxies
- override
- ;;
- 4)
- setgroups
- override
- ;;
- 5)
- echo "$crashcore" | grep -q 'singbox' && set_singbox_adv || set_clash_adv
- sleep 3
- override
- ;;
- 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"
- }
- override
- ;;
- *)
- errornum
- ;;
- esac
+# 添加/管理提供者
+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 -- $@
+ 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$CORECFG_PROVIDER_SUPPORT\033[0m"
+
+ content_line "1) $CORECFG_SET_NAME \033[32m$name\033[0m"
+ content_line "2) $CORECFG_SET_LINK \033[36m$link_info\033[0m"
+ [ -n "$link" ] &&
+ content_line "3) $CORECFG_SET_OVERRIDE"
+ content_line ""
+ content_line "a) $CORECFG_SAVE_PROVIDER"
+ content_line "d) $CORECFG_DEL_PROVIDER"
+ content_line ""
+ content_line "\033[36m$CORECFG_MORE_CONFIG_HINT\033[0m"
+ [ -n "$2" ] &&
+ content_line "b) $CORECFG_GEN_LOCAL_ONE"
+ echo "$2" | grep -q '://' &&
+ content_line "c) $CORECFG_GEN_ONLINE_ONE"
+ echo "$link" | grep -q '^http' &&
+ content_line "e) $CORECFG_GET_ONLINE_DIRECT"
+ echo "$link" | grep -q '^./providers' &&
+ content_line "e) $CORECFG_USE_DIRECT"
+ btm_box "" \
+ "0) $COMMON_BACK"
+ read -r -p "$CORECFG_INPUT_ALNUM> " input
+ case "$input" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ while true; do
+ comp_box "\033[33m$CORECFG_NAME_HINT\033[0m"
+ btm_box "\033[36m$CORECFG_INPUT_NAME\033[0m" \
+ "$CORECFG_OR_BACK"
+ read -r -p "$CORECFG_INPUT> " text
+ text=$(printf "%.12s" "$text" | sed 's/ //g') # 截断12字符+去空格
+ if [ "$text" = 0 ]; then
+ break
+ elif [ -n "$text" ] && [ -z "$(echo "$text" | grep -E '^[0-9]+$')" ] && ! grep -q "^$text " "$CRASHDIR"/configs/providers.cfg 2>/dev/null; then
+ name="$text"
+ common_success
+ break
+ else
+ error_input
+ fi
+ done
+ ;;
+ 2)
+ while true; do
+ comp_box "$CORECFG_LINK_HINT1" \
+ "" \
+ "$CORECFG_LINK_HINT2\n$URI_EXP" \
+ "" \
+ "$CORECFG_LINK_HINT3\033[32m$CRASHDIR/providers\033[0m$CORECFG_LINK_HINT4" \
+ "" \
+ "$CORECFG_LINK_HINT5"
+ 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"
+ btm_box "" \
+ "$CORECFG_INPUT0_BACK"
+ read -r -p "$CORECFG_SELECT_FILE_OR_LINK> " text
+ else
+ btm_box "\033[36m$CORECFG_INPUT_LINK\033[0m" \
+ "$CORECFG_OR_BACK"
+ read -r -p "$CORECFG_INPUT> " text
+ fi
+ text=$(echo "$text" | sed 's/ //g') # 去空格
+ case "$text" in
+ 0)
+ break
+ ;;
+ http*)
+ # 处理订阅链接
+ text=$(echo "$text" | sed 's/ *(.*)//g; s/#.*//g') # 处理注释及超链接
+ link="$text"
+ link_uri=''
+ common_success
+ break
+ ;;
+ [1-9] | [1-9][0-9])
+ # 处理本地文件
+ file=$(printf '%s\n' "$list" | sed -n "${text}p")
+ if [ -s "$CRASHDIR/providers/$file" ]; then
+ link="./providers/$file"
+ [ -z "$name" ] && name="_$(printf "%.12s" "$file" | sed 's/ //g')"
+ link_uri=''
+ common_success
+ break
+ 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' "$(printf '%s' "$text" | sed 's/+/ /g; s/%/\\x/g')" | sed 's/.*#//')
+ common_success
+ break
+ else
+ error_input
+ fi
+ ;;
+ esac
+ done
+ ;;
+ 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
+ msg_alert "\033[31m$CORECFG_FILL_REQUIRED\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
+ msg_alert "\033[31m$CORECFG_FILL_REQUIRED\033[0m"
+ fi
+ ;;
+ d)
+ if [ -n "$name" ] && [ -n "$link" ]; then
+ sed -i "/^$name /d" "$CRASHDIR"/configs/providers.cfg 2>/dev/null
+ msg_alert "\033[32m$COMMON_SUCCESS\033[0m"
+ elif [ -n "$name" ] && [ -n "$link_uri" ]; then
+ sed -i "/^$name /d" "$CRASHDIR"/configs/providers_uri.cfg 2>/dev/null
+ msg_alert "\033[32m$COMMON_SUCCESS\033[0m"
+ fi
+ break
+ ;;
+ e)
+ if [ -n "$link" ]; then
+ comp_box "\033[31m$CORECFG_DANGER1\033[0m" \
+ "\033[31m$CORECFG_DANGER2\033[0m"
+ btm_box "1) $CORECFG_DANGER_CONFIRM" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " 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
+ msg_alert "\033[31m$CORECFG_FILL_REQUIRED\033[0m"
+ fi
+ }
+ else
+ msg_alert "\033[31m$CORECFG_FILL_REQUIRED\033[0m"
+ fi
+ ;;
+ *)
+ error_letter
+ ;;
+ esac
+ done
}
-gen_link_config(){ #选择在线规则
- echo "-----------------------------------------------"
- echo 当前使用规则为:$(grep -aE '^5' "$CRASHDIR"/configs/servers.list | sed -n ""$rule_link"p" | awk '{print $2}')
- grep -aE '^5' "$CRASHDIR"/configs/servers.list | awk '{print " "NR" "$2$4}'
- echo "-----------------------------------------------"
- echo 0 返回上级菜单
- read -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
- echo "-----------------------------------------------"
- echo -e "\033[32m设置成功!返回上级菜单\033[0m"
- fi
-}
-gen_link_server(){ #选择在线服务器
- echo "-----------------------------------------------"
- echo -e "\033[36m以下为互联网采集的第三方服务器,具体安全性请自行斟酌!\033[0m"
- echo -e "\033[32m感谢以下作者的无私奉献!!!\033[0m"
- echo 当前使用后端为:$(grep -aE '^3|^4' "$CRASHDIR"/configs/servers.list | sed -n ""$server_link"p" | awk '{print $3}')
- grep -aE '^3|^4' "$CRASHDIR"/configs/servers.list | awk '{print " "NR" "$3" "$2}'
- echo "-----------------------------------------------"
- echo 0 返回上级菜单
- read -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
- echo "-----------------------------------------------"
- echo -e "\033[32m设置成功!返回上级菜单\033[0m"
- fi
-}
-gen_link_flt(){ #在线生成节点过滤
- [ -z "$exclude" ] && exclude="未设置"
- echo "-----------------------------------------------"
- echo -e "\033[33m当前过滤关键字:\033[47;30m$exclude\033[0m"
- echo "-----------------------------------------------"
- echo -e "\033[33m匹配关键字的节点会在导入时被【屏蔽】!!!\033[0m"
- echo -e "多个关键字可以用\033[30;47m | \033[0m号分隔"
- echo -e "\033[32m支持正则表达式\033[0m,空格请使用\033[30;47m + \033[0m号替代"
- echo "-----------------------------------------------"
- echo -e " 000 \033[31m删除\033[0m关键字"
- echo -e " 回车 取消输入并返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入关键字 > " exclude
- if [ "$exclude" = '000' ]; then
- echo "-----------------------------------------------"
- exclude=''
- echo -e "\033[31m 已删除节点过滤关键字!!!\033[0m"
- fi
- setconfig exclude "'$exclude'"
-}
-gen_link_ele(){ #在线生成节点筛选
- [ -z "$include" ] && include="未设置"
- echo "-----------------------------------------------"
- echo -e "\033[33m当前筛选关键字:\033[47;30m$include\033[0m"
- echo "-----------------------------------------------"
- echo -e "\033[33m仅有匹配关键字的节点才会被【导入】!!!\033[0m"
- echo -e "多个关键字可以用\033[30;47m | \033[0m号分隔"
- echo -e "\033[32m支持正则表达式\033[0m,空格请使用\033[30;47m + \033[0m号替代"
- echo "-----------------------------------------------"
- echo -e " 000 \033[31m删除\033[0m关键字"
- echo -e " 回车 取消输入并返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入关键字 > " include
- if [ "$include" = '000' ]; then
- echo "-----------------------------------------------"
- include=''
- echo -e "\033[31m 已删除节点匹配关键字!!!\033[0m"
- fi
- setconfig include "'$include'"
-}
-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
-}
-gen_core_config_link(){ #在线生成工具
- echo "-----------------------------------------------"
- echo -e "\033[30;47m 欢迎使用在线生成配置文件功能!\033[0m"
- echo "-----------------------------------------------"
- #设置输入循环
- i=1
- while [ $i -le 99 ]
- do
- echo "-----------------------------------------------"
- echo -e "\033[33m本功能依赖第三方在线subconverter服务实现,脚本本身不提供任何代理服务!\033[0m"
- echo -e "\033[31m严禁使用本脚本从事任何非法活动,否则一切后果请自负!\033[0m"
- echo "-----------------------------------------------"
- echo -e "支持批量(<=99)导入订阅链接、分享链接"
- echo "-----------------------------------------------"
- echo -e " 1 \033[36m开始生成配置文件\033[0m(原文件将被备份)"
- echo -e " 2 设置\033[31m节点过滤\033[0m关键字 \033[47;30m$exclude\033[0m"
- echo -e " 3 设置\033[32m节点筛选\033[0m关键字 \033[47;30m$include\033[0m"
- echo -e " 4 选取在线\033[33m配置规则模版\033[0m"
- echo -e " 5 \033[0m选取在线生成服务器\033[0m"
- echo -e " 0 \033[31m撤销输入并返回上级菜单\033[0m"
- echo "-----------------------------------------------"
- read -p "请直接输入第${i}个链接或对应数字选项 > " link
- link=$(echo $link | sed 's/\&/%26/g') #处理分隔符
- test=$(echo $link | grep "://")
- link=`echo ${link/\#*/''}` #删除链接附带的注释内容
- link=`echo ${link/\ \(*\)/''}` #删除恶心的超链接内容
- link=`echo ${link/*\&url\=/""}` #将完整链接还原成单一链接
- link=`echo ${link/\&config\=*/""}` #将完整链接还原成单一链接
-
- if [ -n "$test" ];then
- if [ -z "$Url_link" ];then
- Url_link="$link"
- else
- Url_link="$Url_link"\|"$link"
- fi
- i=$((i+1))
-
- elif [ "$link" = '1' ]; then
- if [ -n "$Url_link" ];then
- i=100
- #将用户链接写入配置
- Url="$Url_link"
- Https=''
- setconfig Https
- setconfig Url "'$Url'"
- #获取在线yaml文件
- jump_core_config
- else
- echo "-----------------------------------------------"
- echo -e "\033[31m请先输入订阅或分享链接!\033[0m"
- sleep 1
- fi
-
- elif [ "$link" = '2' ]; then
- gen_link_flt
-
- elif [ "$link" = '3' ]; then
- gen_link_ele
-
- elif [ "$link" = '4' ]; then
- gen_link_config
-
- elif [ "$link" = '5' ]; then
- gen_link_server
-
- elif [ "$link" = 0 ];then
- Url_link=""
- i=100
-
- else
- echo "-----------------------------------------------"
- echo -e "\033[31m请输入正确的链接或者数字!\033[0m"
- sleep 1
- fi
- done
-}
-set_core_config_link(){ #直接导入配置
- echo "-----------------------------------------------"
- echo -e "\033[32m仅限导入完整的配置文件链接!!!\033[0m"
- echo "-----------------------------------------------"
- echo -e "注意:\033[31m此功能不兼容“跳过证书验证”功能,部分老旧\n设备可能出现x509报错导致节点不通\033[0m"
- echo -e "你也可以搭配在线订阅转换网站或者自建SubStore使用"
- echo "$crashcore" | grep -q 'singbox' &&echo -e "singbox内核建议使用\033[32;4mhttps://subv.jwsc.eu.org/\033[0m转换"
- echo "-----------------------------------------------"
- echo -e "\033[33m0 返回上级菜单\033[0m"
- echo "-----------------------------------------------"
- read -p "请输入完整链接 > " link
- test=$(echo $link | grep -iE "tp.*://" )
- link=`echo ${link/\ \(*\)/''}` #删除恶心的超链接内容
- link=`echo ${link//\&/\\\&}` #处理分隔符
- if [ -n "$link" -a -n "$test" ];then
- echo "-----------------------------------------------"
- echo -e 请检查输入的链接是否正确:
- echo -e "\033[4;32m$link\033[0m"
- read -p "确认导入配置文件?原配置文件将被备份![1/0] > " res
- if [ "$res" = '1' ]; then
- #将用户链接写入配置
- Url=''
- Https="$link"
- setconfig Https "'$Https'"
- setconfig Url
- #获取在线yaml文件
- jump_core_config
- else
- set_core_config_link
- fi
- elif [ "$link" = 0 ];then
- i=
- else
- echo "-----------------------------------------------"
- echo -e "\033[31m请输入正确的配置文件链接地址!!!\033[0m"
- echo -e "\033[33m仅支持http、https、ftp以及ftps链接!\033[0m"
- sleep 1
- set_core_config_link
- fi
+# 保存
+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$CORECFG_FILL_REQUIRED\033[0m"
+ return 1
+ fi
}
-#配置文件主界面
-set_core_config(){
- [ -z "$rule_link" ] && rule_link=1
- [ -z "$server_link" ] && server_link=1
- echo "$crashcore" | grep -q 'singbox' && config_path="$JSONSDIR"/config.json || config_path="$YAMLSDIR"/config.yaml
- echo "-----------------------------------------------"
- echo -e "\033[30;47m ShellCrash配置文件管理\033[0m"
- echo "-----------------------------------------------"
- echo -e " 1 在线\033[32m生成配置文件\033[0m(基于Subconverter订阅转换)"
- if [ -f "$CRASHDIR"/v2b_api.sh ];then
- echo -e " 2 登录\033[33m获取订阅(推荐!)\033[0m"
- else
- echo -e " 2 在线\033[33m获取配置文件\033[0m(基于订阅提供者)"
- fi
- echo -e " 3 本地\033[32m生成配置文件\033[0m(基于内核providers,推荐!)"
- echo -e " 4 本地\033[33m上传完整配置文件\033[0m"
- echo -e " 5 设置\033[36m自动更新\033[0m"
- echo -e " 6 \033[32m自定义\033[0m配置文件"
- echo -e " 7 \033[33m更新\033[0m配置文件"
- echo -e " 8 \033[36m还原\033[0m配置文件"
- echo -e " 9 自定义浏览器UA \033[32m$user_agent\033[0m"
- echo "-----------------------------------------------"
- [ "$inuserguide" = 1 ] || echo -e " 0 返回上级菜单"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0)
- ;;
- 1)
- if [ -n "$Url" ];then
- echo "-----------------------------------------------"
- echo -e "\033[33m检测到已记录的链接内容:\033[0m"
- echo -e "\033[4;32m$Url\033[0m"
- echo "-----------------------------------------------"
- read -p "清空链接/追加导入?[1/0] > " res
- if [ "$res" = '1' ]; then
- Url_link=""
- echo "-----------------------------------------------"
- echo -e "\033[31m链接已清空!\033[0m"
- else
- Url_link=$Url
- fi
- fi
- gen_core_config_link
- set_core_config
- ;;
- 2)
- if [ -f "$CRASHDIR"/v2b_api.sh ];then
- . "$CRASHDIR"/v2b_api.sh
- set_core_config
- else
- set_core_config_link
- fi
- set_core_config
- ;;
- 3)
- if [ "$crashcore" = meta -o "$crashcore" = clashpre ];then
- coretype=clash
- setproviders
- elif [ "$crashcore" = singboxr ];then
- coretype=singbox
- setproviders
- else
- echo -e "\033[33msingbox官方内核及Clash基础内核不支持此功能,请先更换内核!\033[0m"
- sleep 1
- checkupdate && setcore
- fi
- set_core_config
- ;;
- 4)
- echo "-----------------------------------------------"
- echo -e "\033[33m请将本地配置文件上传到/tmp目录并重命名为config.yaml或者config.json\033[0m"
- echo -e "\033[32m之后重新运行本脚本即可自动弹出导入提示!\033[0m"
- exit
- ;;
- 5)
- . "$CRASHDIR"/menus/5_task.sh && task_menu
- set_core_config
- ;;
- 6)
- checkcfg=$(cat $CFG_PATH)
- override
- if [ -n "$PID" ];then
- checkcfg_new=$(cat $CFG_PATH)
- [ "$checkcfg" != "$checkcfg_new" ] && checkrestart
- fi
- set_core_config
- ;;
- 7)
- if [ -z "$Url" -a -z "$Https" ];then
- echo "-----------------------------------------------"
- echo -e "\033[31m没有找到你的配置文件/订阅链接!请先输入链接!\033[0m"
- sleep 1
- set_core_config
- else
- echo "-----------------------------------------------"
- echo -e "\033[33m当前系统记录的链接为:\033[0m"
- echo -e "\033[4;32m$Url$Https\033[0m"
- echo "-----------------------------------------------"
- read -p "确认更新配置文件?[1/0] > " res
- if [ "$res" = '1' ]; then
- jump_core_config
- else
- set_core_config
- fi
- fi
- ;;
- 8)
- if [ ! -f ${config_path}.bak ];then
- echo "-----------------------------------------------"
- echo -e "\033[31m没有找到配置文件的备份!\033[0m"
- set_core_config
- else
- echo "-----------------------------------------------"
- echo -e 备份文件共有"\033[32m`wc -l < ${config_path}.bak`\033[0m"行内容,当前文件共有"\033[32m`wc -l < ${config_path}`\033[0m"行内容
- read -p "确认还原配置文件?此操作不可逆![1/0] > " res
- if [ "$res" = '1' ]; then
- mv ${config_path}.bak ${config_path}
- echo "----------------------------------------------"
- echo -e "\033[32m配置文件已还原!请手动重启服务!\033[0m"
- sleep 1
- else
- echo "-----------------------------------------------"
- echo -e "\033[31m操作已取消!返回上级菜单!\033[0m"
- set_core_config
- fi
- fi
- ;;
- 9)
- echo "-----------------------------------------------"
- echo -e "\033[36m如果6-1或者6-2无法正确获取配置文件时可以尝试使用\033[0m"
- echo -e " 1 使用自动UA"
- echo -e " 2 不使用UA"
- echo -e " 3 使用自定义UA:\033[32m$user_agent\033[0m"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0)
- user_agent=''
- ;;
- 1)
- user_agent='auto'
- ;;
- 2)
- user_agent='none'
- ;;
- 3)
- read -p "请输入自定义UA(不要包含空格和特殊符号!) > " text
- [ -n "$text" ] && user_agent="$text"
- ;;
- *)
- errornum
- ;;
- esac
- [ "$num" -le 3 ] && setconfig user_agent "$user_agent"
- set_core_config
- ;;
- *)
- errornum
- ;;
- esac
+# 本地生成覆写
+custproviders() {
+ while true; do
+ top_box "1) $CORECFG_INTERVAL1\033[47;30m$interval\033[0m $CORECFG_MIN" \
+ "2) $CORECFG_INTERVAL2\033[47;30m$interval2\033[0m $CORECFG_HOUR"
+ echo "$link" | grep -q '^http' &&
+ content_line "3) $CORECFG_SET_UA\033[47;30m$ua\033[0m"
+ btm_box "4) $CORECFG_SET_EXCLUDE\033[47;30m$exclude_w\033[0m" \
+ "5) $CORECFG_SET_INCLUDE\033[47;30m$include_w\033[0m" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ while true; do
+ comp_box "$CORECFG_CUR_INTERVAL$interval $CORECFG_MIN"
+ btm_box "\033[36m$CORECFG_INPUT_INTERVAL1\033[0m" \
+ "$CORECFG_RESET_INTERVAL1" \
+ "$CORECFG_OR_BACK"
+ read -r -p "$CORECFG_INPUT> " num
+ if [ "$num" = "r" ]; then
+ interval=3
+ elif [ -n "$num" ] && [ "$num" -eq "$num" ] 2>/dev/null; then
+ interval="$num"
+ else
+ errornum
+ continue
+ fi
+ common_success
+ break
+ done
+ ;;
+ 2)
+ while true; do
+ comp_box "$CORECFG_CUR_INTERVAL$interval $CORECFG_MIN"
+ btm_box "\033[36m$CORECFG_INPUT_INTERVAL2\033[0m" \
+ "$CORECFG_RESET_INTERVAL2" \
+ "$CORECFG_OR_BACK"
+ read -r -p "$CORECFG_INPUT> " num
+ if [ "$num" = "r" ]; then
+ interval2=12
+ elif [ -n "$num" ] && [ "$num" -eq "$num" ] 2>/dev/null; then
+ interval2="$num"
+ else
+ errornum
+ continue
+ fi
+ common_success
+ break
+ done
+ ;;
+ 3)
+ if [ -z "$ua" ]; then
+ comp_box "$CORECFG_CUR_UA_NONE"
+ else
+ comp_box "$CORECFG_CUR_UA$ua"
+ fi
+ btm_box "\033[36m$CORECFG_INPUT_UA\033[0m" \
+ "$CORECFG_RESET_UA" \
+ "$CORECFG_OR_BACK"
+ read -r -p "$CORECFG_INPUT> " text
+ case "$text" in
+ 0)
+ continue
+ ;;
+ r)
+ ua='clash.meta'
+ ;;
+ *)
+ ua="$text"
+ ;;
+ esac
+ common_success
+ ;;
+ 4)
+ if [ -z "$exclude_w" ]; then
+ comp_box "$CORECFG_CUR_EXCLUDE_NONE"
+ else
+ comp_box "$CORECFG_CUR_EXCLUDE$exclude_w"
+ fi
+
+ btm_box "\033[36m$CORECFG_INPUT_EXCLUDE\033[0m" \
+ "$CORECFG_CLEAR_EXCLUDE" \
+ "$CORECFG_OR_BACK"
+ read -r -p "$CORECFG_INPUT> " text
+ text=$(echo "$text" | sed 's/ //g') # 去空格
+ case "$text" in
+ 0)
+ continue
+ ;;
+ c)
+ exclude_w=''
+ ;;
+ *)
+ exclude_w="$text"
+ ;;
+ esac
+ common_success
+ ;;
+ 5)
+ if [ -z "$include_w" ]; then
+ comp_box "$CORECFG_CUR_INCLUDE_NONE"
+ else
+ comp_box "$CORECFG_CUR_INCLUDE$include_w"
+ fi
+ btm_box "\033[36m$CORECFG_INPUT_INCLUDE\033[0m" \
+ "$CORECFG_CLEAR_INCLUDE" \
+ "$CORECFG_OR_BACK"
+ read -r -p "$CORECFG_INPUT> " text
+ text=$(echo "$text" | sed 's/ //g') # 去空格
+ case "$text" in
+ 0)
+ continue
+ ;;
+ c)
+ include_w=''
+ ;;
+ *)
+ include_w="$text"
+ ;;
+ esac
+ common_success
+ ;;
+ *)
+ error_letter
+ ;;
+ esac
+ done
+}
+
+# 调用工具在线获取配置文件
+jump_core_config() {
+ . "$CRASHDIR"/starts/core_config.sh && get_core_config
+ if [ "$?" = 0 ]; then
+ if [ "$inuserguide" != 1 ]; then
+ comp_box "$CORECFG_START_APPLY"
+ btm_box "1) $CORECFG_YES" \
+ "0) $CORECFG_NO"
+ read -r -p "$COMMON_INPUT> " res
+ if [ "$res" = 1 ]; then
+ start_core
+ else
+ main_menu
+ fi
+ exit
+ fi
+ fi
}
diff --git a/scripts/menus/7_gateway.sh b/scripts/menus/7_gateway.sh
index 1d23913e..7338b9f9 100644
--- a/scripts/menus/7_gateway.sh
+++ b/scripts/menus/7_gateway.sh
@@ -7,336 +7,375 @@ __IS_MODULE_7_GATEWAY_LOADED=1
. "$GT_CFG_PATH"
. "$CRASHDIR"/menus/check_port.sh
. "$CRASHDIR"/libs/gen_base64.sh
+load_lang 7_gateway
-#访问与控制主菜单
-gateway(){
- echo "-----------------------------------------------"
- echo -e "\033[30;47m欢迎使用访问与控制菜单:\033[0m"
- echo "-----------------------------------------------"
- echo -e " 1 配置\033[33m公网访问防火墙 \033[32m$fw_wan\033[0m"
- echo -e " 2 配置\033[36mTelegram专属控制机器人 \033[32m$bot_tg_service\033[0m"
- echo -e " 3 配置\033[36mDDNS自动域名\033[0m"
- [ "$disoverride" != "1" ] && {
- echo -e " 4 自定义\033[33m公网Vmess入站\033[0m节点 \033[32m$vms_service\033[0m"
- echo -e " 5 自定义\033[33m公网ShadowSocks入站\033[0m节点 \033[32m$sss_service\033[0m"
- echo -e " 6 配置\033[36mTailscale内网穿透\033[0m(限Singbox) \033[32m$ts_service\033[0m"
- echo -e " 7 配置\033[36mWireguard客户端\033[0m(限Singbox) \033[32m$wg_service\033[0m"
- }
- echo -e " 0 返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0) ;;
- 1)
- echo "-----------------------------------------------"
- if [ -n "$(pidof CrashCore)" ] && [ "$firewall_mod" = 'iptables' ]; then
- read -p "需要先停止服务,是否继续?(1/0) > " res
- [ "$res" = 1 ] && "$CRASHDIR"/start.sh stop && set_fw_wan
- else
- set_fw_wan
- fi
- gateway
- ;;
- 2)
- set_bot_tg
- gateway
- ;;
- 3)
- . "$CRASHDIR"/menus/ddns.sh && ddns_menu
- gateway
- ;;
- 4)
- set_vmess
- gateway
- ;;
- 5)
- set_shadowsocks
- gateway
- ;;
- 6)
- if echo "$crashcore" | grep -q 'sing';then
- set_tailscale
- else
- echo -e "\033[33m$crashcore内核暂不支持此功能,请先更换内核!\033[0m"
- sleep 1
- fi
- gateway
- ;;
- 7)
- if echo "$crashcore" | grep -q 'sing';then
- set_wireguard
- else
- echo -e "\033[33m$crashcore内核暂不支持此功能,请先更换内核!\033[0m"
- sleep 1
- fi
- gateway
- ;;
- *) errornum ;;
- esac
+# 访问与控制主菜单
+gateway() {
+ while true; do
+ comp_box "\033[30;47m$GW_TITLE\033[0m"
+ content_line "1) $GW_MENU_FW_WAN \033[32m$fw_wan\033[0m"
+ content_line "2) $GW_MENU_TG_BOT \033[32m$bot_tg_service\033[0m"
+ content_line "3) $GW_MENU_DDNS"
+ [ "$disoverride" != "1" ] && {
+ content_line "4) $GW_MENU_VMESS \033[32m$vms_service\033[0m"
+ content_line "5) $GW_MENU_SHADOWSOCKS \033[32m$sss_service\033[0m"
+ content_line "6) $GW_MENU_TS \033[32m$ts_service\033[0m"
+ content_line "7) $GW_MENU_WG \033[32m$wg_service\033[0m"
+ }
+ btm_box "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ if [ -n "$(pidof CrashCore)" ] && [ "$firewall_mod" = 'iptables' ]; then
+ comp_box "\033[33m$GW_FW_STOP_WARN\033[0m" \
+ "$GW_CONFIRM_CONTINUE"
+ btm_box "1) $GW_YES" \
+ "0) $GW_NO_BACK"
+ read -r -p "$COMMON_INPUT> " 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
+ msg_alert "\033[33m$crashcore$GW_CORE_UNSUPPORTED\033[0m"
+ fi
+ ;;
+ 7)
+ if echo "$crashcore" | grep -q 'sing'; then
+ set_wireguard
+ else
+ msg_alert "\033[33m$crashcore$GW_CORE_UNSUPPORTED\033[0m"
+ fi
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
}
-#公网防火墙
+
+# 公网防火墙
set_fw_wan() {
- [ -z "$fw_wan" ] && fw_wan=ON
- echo "-----------------------------------------------"
- echo -e "\033[31m注意:\033[0m如在vps运行,还需在vps安全策略对相关端口同时放行"
- [ -n "$fw_wan_ports" ] &&
- echo -e "当前手动放行端口:\033[36m$fw_wan_ports\033[0m"
- [ -n "$vms_port$sss_port" ] &&
- echo -e "当前自动放行端口:\033[36m$vms_port $sss_port\033[0m"
- echo -e "默认拦截端口:\033[33m$mix_port,$db_port\033[0m"
- echo "-----------------------------------------------"
- echo -e " 1 启用/关闭公网防火墙: \033[36m$fw_wan\033[0m"
- echo -e " 2 添加放行端口(可包含默认拦截端口)"
- echo -e " 3 移除指定手动放行端口"
- echo -e " 4 清空全部手动放行端口"
- echo -e " 0 返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case $num in
- 1)
- if [ "$fw_wan" = ON ];then
- read -p "确认关闭防火墙?这会带来极大的安全隐患!(1/0) > " res
- [ "$res" = 1 ] && fw_wan=OFF || fw_wan=ON
- else
- fw_wan=ON
- fi
- setconfig fw_wan "$fw_wan"
- set_fw_wan
- ;;
- 2)
- port_count=$(echo "$fw_wan_ports" | awk -F',' '{print NF}' )
- if [ "$port_count" -ge 10 ];then
- echo -e "\033[31m最多支持设置放行10个端口,请先减少一些!\033[0m"
- else
- read -p "请输入要放行的端口号 > " port
- if echo ",$fw_wan_ports," | grep -q ",$port,";then
- echo -e "\033[31m输入错误!请勿重复添加!\033[0m"
- elif [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
- echo -e "\033[31m输入错误!请输入正确的数值(1-65535)!\033[0m"
- else
- fw_wan_ports=$(echo "$fw_wan_ports,$port" | sed "s/^,//")
- setconfig fw_wan_ports "$fw_wan_ports"
- fi
- fi
- sleep 1
- set_fw_wan
- ;;
- 3)
- read -p "请输入要移除的端口号 > " port
- if echo ",$fw_wan_ports," | grep -q ",$port,";then
- if [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
- echo -e "\033[31m输入错误!请输入正确的数值(1-65535)!\033[0m"
- else
- fw_wan_ports=$(echo ",$fw_wan_ports," | sed "s/,$port//; s/^,//; s/,$//")
- setconfig fw_wan_ports "$fw_wan_ports"
- fi
- else
- echo -e "\033[31m输入错误!请输入已添加过的端口!\033[0m"
- fi
- sleep 1
- set_fw_wan
- ;;
- 4)
- fw_wan_ports=''
- setconfig fw_wan_ports
- sleep 1
- set_fw_wan
- ;;
- *)
- errornum
- ;;
- esac
+ while true; do
+ [ -z "$fw_wan" ] && fw_wan=ON
+ line_break
+ separator_line "="
+ content_line "\033[31m$GW_WARN\033[0m$GW_FW_VPS_HINT"
+ [ -n "$fw_wan_ports" ] &&
+ content_line "$GW_FW_MANUAL_PORTS\033[36m$fw_wan_ports\033[0m"
+ [ -n "$vms_port$sss_port" ] &&
+ content_line "$GW_FW_AUTO_PORTS\033[36m$vms_port $sss_port\033[0m"
+ content_line "$GW_FW_DEFAULT_BLOCK\033[33m$mix_port,$db_port\033[0m"
+ separator_line "="
+ btm_box "1) $GW_FW_TOGGLE\033[36m$fw_wan\033[0m" \
+ "2) $GW_FW_ADD_PORT" \
+ "3) $GW_FW_REMOVE_PORT" \
+ "4) $GW_FW_CLEAR_PORTS" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case $num in
+ "" | 0)
+ break
+ ;;
+ 1)
+ if [ "$fw_wan" = ON ]; then
+ comp_box "$GW_FW_DISABLE_CONFIRM" \
+ "$GW_FW_DISABLE_RISK"
+ btm_box "1) $GW_YES" \
+ "0) $GW_NO_BACK"
+ read -r -p "$COMMON_INPUT> " res
+ if [ "$res" = 1 ]; then
+ fw_wan=OFF
+ else
+ fw_wan=ON
+ fi
+ else
+ fw_wan=ON
+ fi
+ setconfig fw_wan "$fw_wan"
+ ;;
+ 2)
+ port_count=$(echo "$fw_wan_ports" | awk -F',' '{print NF}')
+ if [ "$port_count" -ge 10 ]; then
+ msg_alert "\033[31m$GW_FW_PORT_LIMIT\033[0m"
+ else
+ line_break
+ read -r -p "$GW_INPUT_ALLOW_PORT> " port
+ if echo ",$fw_wan_ports," | grep -q ",$port,"; then
+ msg_alert "\033[31m$GW_ERR_DUP_PORT\033[0m"
+ elif [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
+ msg_alert "\033[31m$GW_ERR_PORT_RANGE\033[0m"
+ else
+ fw_wan_ports=$(echo "$fw_wan_ports,$port" | sed "s/^,//")
+ if setconfig fw_wan_ports "$fw_wan_ports"; then
+ common_success
+ else
+ common_faileds
+ fi
+ fi
+ fi
+ ;;
+ 3)
+ while true; do
+ comp_box "\033[36m$GW_INPUT_REMOVE_PORT\033[0m" \
+ "$GW_INPUT_0_BACK"
+ read -r -p "$GW_INPUT_PLAIN> " port
+ if [ "$port" = 0 ]; then
+ break
+ elif echo ",$fw_wan_ports," | grep -q ",$port,"; then
+ if [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
+ msg_alert "\033[31m$GW_ERR_INPUT\033[0m" \
+ "\033[31m$GW_ERR_PORT_RANGE\033[0m"
+ else
+ fw_wan_ports=$(echo ",$fw_wan_ports," | sed "s/,$port//; s/^,//; s/,$//")
+ setconfig fw_wan_ports "$fw_wan_ports"
+ break
+ fi
+ else
+ msg_alert "\033[31m$GW_ERR_INPUT\033[0m" \
+ "\033[31m$GW_ERR_PORT_NOT_FOUND\033[0m"
+ fi
+ done
+ ;;
+ 4)
+ fw_wan_ports=''
+ setconfig fw_wan_ports
+ msg_alert "\033[32m$GW_OK\033[0m"
+ ;;
+ *)
+ errornum
+ ;;
+ 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 < " num
- case "$num" in
- 0) ;;
- 1)
- . "$GT_CFG_PATH"
- if [ -n "$TG_CHATID" ];then
- set_bot_tg_service
- else
- echo -e "\033[31m请先绑定TG-BOT!\033[0m"
- fi
- sleep 1
- set_bot_tg
- ;;
- 2)
- if [ -n "$chat_ID" ] && [ -n "$push_TG" ] && [ "$push_TG" != 'publictoken' ]; then
- read -p "检测到已经绑定了TG推送BOT,是否直接使用?(1/0) > " res
- if [ "$res" = 1 ]; then
- TOKEN="$push_TG"
- set_bot_tg_config
- set_bot_tg
- return
- fi
- fi
- set_bot_tg_init
- set_bot_tg
- ;;
- 3)
- if [ "$TG_menupush" = ON ];then
- TG_menupush=OFF
- else
- TG_menupush=ON
- fi
- setconfig TG_menupush "$TG_menupush" "$GT_CFG_PATH"
- set_bot_tg
- ;;
- *)
- errornum
- ;;
- esac
+
+set_bot_tg() {
+ while true; do
+ [ -n "$ts_auth_key" ] && ts_auth_key_info="$GW_SET"
+ [ -n "$TG_CHATID" ] && TG_CHATID_info="$GW_BOUND"
+ comp_box "\033[31m$GW_WARN\033[0m$GW_TG_WARN"
+ btm_box "1) $GW_TG_TOGGLE \033[32m$bot_tg_service\033[0m" \
+ "2) $GW_TG_BIND \033[32m$TG_CHATID_info\033[0m" \
+ "3) $GW_TG_MENUPUSH \033[32m$TG_menupush\033[0m" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ . "$GT_CFG_PATH"
+ if [ -n "$TG_CHATID" ]; then
+ set_bot_tg_service
+ else
+ msg_alert "\033[31m$GW_TG_BIND_FIRST\033[0m"
+ fi
+ ;;
+ 2)
+ if [ -n "$chat_ID" ] && [ -n "$push_TG" ] && [ "$push_TG" != 'publictoken' ]; then
+ comp_box "$GW_TG_BOUND_DETECTED" \
+ "$GW_TG_USE_DIRECT"
+ btm_box "1) $GW_YES" \
+ "0) $GW_NO"
+ read -r -p "$COMMON_INPUT> " res
+ if [ "$res" = 1 ]; then
+ TOKEN="$push_TG"
+ set_bot_tg_config
+ continue
+ fi
+ fi
+ set_bot_tg_init
+ ;;
+ 3)
+ if [ "$TG_menupush" = ON ]; then
+ TG_menupush=OFF
+ else
+ TG_menupush=ON
+ fi
+ setconfig TG_menupush "$TG_menupush" "$GT_CFG_PATH"
+ set_bot_tg
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
}
-#自定义入站
-set_vmess(){
- echo "-----------------------------------------------"
- echo -e "\033[31m注意:\033[0m设置的端口会添加到公网访问防火墙并自动放行!\n 脚本只提供基础功能,更多需求请用自定义配置文件功能!"
- echo -e " \033[31m切勿用于搭建违法翻墙节点,违者后果自负!\033[0m"
- echo "-----------------------------------------------"
- echo -e " 1 \033[32m启用/关闭\033[0mVmess入站 \033[32m$vms_service\033[0m"
- echo "-----------------------------------------------"
- echo -e " 2 设置\033[36m监听端口\033[0m: \033[36m$vms_port\033[0m"
- echo -e " 3 设置\033[33mWS-path(可选)\033[0m: \033[33m$vms_ws_path\033[0m"
- echo -e " 4 设置\033[36m秘钥-uuid\033[0m: \033[36m$vms_uuid\033[0m"
- echo -e " 5 一键生成\033[32m随机秘钥\033[0m"
- echo -e " 6 设置\033[36m混淆host(可选)\033[0m: \033[33m$vms_host\033[0m"
- gen_base64 1 >/dev/null 2>&1 &&
- echo -e " 7 一键生成\033[32m分享链接\033[0m"
- echo -e " 0 返回上级菜单 \033[0m"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0) ;;
- 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
- echo -e "\033[31m请先完成必选设置!\033[0m"
- sleep 1
- fi
- fi
- set_vmess
- ;;
- 2)
- read -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
- set_vmess
- ;;
- 3)
- read -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
- echo -e "\033[31m不是合法的path路径,必须以【/】开头!\033[0m"
- sleep 1
- fi
- set_vmess
- ;;
- 4)
- read -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
- echo -e "\033[31m不是合法的UUID格式,请重新输入或使用随机生成功能!\033[0m"
- sleep 1
- fi
- set_vmess
- ;;
- 5)
- vms_uuid=$(cat /proc/sys/kernel/random/uuid)
- setconfig vms_uuid "$vms_uuid" "$GT_CFG_PATH"
- sleep 1
- set_vmess
- ;;
- 6)
- read -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
- set_vmess
- ;;
- 7)
- read -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 </dev/null 2>&1 &&
+ content_line "6) $GW_SET_OBFS_HOST \033[33m$vms_host\033[0m"
+ btm_box "7) $GW_GEN_SHARE_LINK" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " 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
+ msg_alert "\033[31m$GW_FILL_REQUIRED\033[0m"
+ fi
+ fi
+ ;;
+ 2)
+ line_break
+ read -r -p "$GW_INPUT_PORT_DEL0> " text
+ if [ "$text" = 0 ]; then
+ vms_port=''
+ setconfig vms_port "" "$GT_CFG_PATH"
+ elif check_port "$text"; then
+ if echo "|$mix_port|$redir_port|$dns_port|$db_port|" | grep -q "|$text|"; then
+ msg_alert "\033[31m$CHECK_PORT_DUP_ERR\033[0m"
+ sleep 1
+ else
+ vms_port="$text"
+ setconfig vms_port "$text" "$GT_CFG_PATH"
+ fi
+ else
+ sleep 1
+ fi
+ ;;
+ 3)
+ line_break
+ read -r -p "$GW_INPUT_WSPATH> " 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
+ msg_alert "\033[31m$GW_ERR_WSPATH\033[0m"
+ fi
+ ;;
+ 4)
+ line_break
+ read -r -p "$GW_INPUT_UUID> " 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
+ msg_alert "\033[31m$GW_ERR_UUID\033[0m"
+ 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 "$GW_INPUT_OBFS_HOST> " 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 "$GW_INPUT_HOST> " host_wan
+ if [ -n "$host_wan" ] && [ -n "$vms_port" ] && [ -n "$vms_uuid" ]; then
+ [ -n "$vms_ws_path" ] && vms_net=ws
+ vms_json=$(
+ cat </dev/null 2>&1 &&
- echo -e " 5 一键生成分享链接"
- echo -e " 0 返回上级菜单 \033[0m"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0) ;;
- 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
- echo -e "\033[31m请先完成必选设置!\033[0m"
- sleep 1
- fi
- fi
- set_shadowsocks
- ;;
- 2)
- read -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
- set_shadowsocks
- ;;
- 3)
- echo "-----------------------------------------------"
- echo -e " 1 \033[32mxchacha20-ietf-poly1305\033[0m"
- echo -e " 2 \033[32mchacha20-ietf-poly1305\033[0m"
- echo -e " 3 \033[32maes-128-gcm\033[0m"
- echo -e " 4 \033[32maes-256-gcm\033[0m"
- gen_random 1 >/dev/null && {
- echo "-----------------------------------------------"
- echo -e "\033[31m注意:\033[0m2022系列加密必须使用随机生成的password!"
- echo -e " 5 \033[32m2022-blake3-chacha20-poly1305\033[0m"
- echo -e " 6 \033[32m2022-blake3-aes-128-gcm\033[0m"
- echo -e " 7 \033[32m2022-blake3-aes-256-gcm\033[0m"
- }
- echo "-----------------------------------------------"
- echo -e " 0 返回上级菜单"
- read -p "请选择要使用的加密协议 > " num
- case "$num" in
- 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)
- ;;
- *)
- ;;
- esac
- setconfig sss_cipher "$sss_cipher" "$GT_CFG_PATH"
- setconfig sss_pwd "$sss_pwd" "$GT_CFG_PATH"
- set_shadowsocks
- ;;
- 4)
- if echo "$sss_cipher" |grep -q '2022-blake3';then
- echo -e "\033[31m注意:\033[0m2022系列加密必须使用脚本随机生成的password!"
- sleep 1
- else
- read -p "请输入秘钥(输入0删除) > " text
- [ "$text" = 0 ] && sss_pwd='' || sss_pwd="$text"
- setconfig sss_pwd "$text" "$GT_CFG_PATH"
- fi
- set_shadowsocks
- ;;
- 5)
- read -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"
- echo "-----------------------------------------------"
- echo -e "你的分享链接是(请勿随意分享给他人):\n\033[32m$ss_link\033[0m"
- else
- echo -e "\033[31m请先完成必选设置!\033[0m"
- fi
- sleep 1
- set_shadowsocks
- ;;
- *) errornum ;;
- esac
-}
-#自定义端点
-set_tailscale(){
- [ -n "$ts_auth_key" ] && ts_auth_key_info='*********'
- echo "-----------------------------------------------"
- echo -e "\033[31m注意:\033[0m脚本默认内核为了节约内存没有编译Tailscale模块\n如需使用请先前往自定义内核更新完整版内核文件!"
- echo -e "创建秘钥:\033[32;4mhttps://login.tailscale.com/admin/settings/keys\033[0m"
- echo -e "访问非本机目标需允许通告:\033[32;4mhttps://login.tailscale.com\033[0m"
- echo -e "访问非本机目标需在终端设置使用Subnet或EXIT-NODE模式"
- echo "-----------------------------------------------"
- echo -e " 1 \033[32m启用/关闭\033[0mTailscale服务 \033[32m$ts_service\033[0m"
- echo -e " 2 设置\033[36m秘钥\033[0m(Auth Key) $ts_auth_key_info"
- echo -e " 3 通告路由\033[33m内网地址\033[0m(Subnet) \033[36m$ts_subnet\033[0m"
- echo -e " 4 通告路由\033[31m全部流量\033[0m(EXIT-NODE) \033[36m$ts_exit_node\033[0m"
- echo -e " 5 设置\033[36m设备名称\033[0m(可选) $ts_hostname"
- echo -e " 0 返回上级菜单 \033[0m"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0) ;;
- 1)
- if [ -n "$ts_auth_key" ];then
- [ "$ts_service" = ON ] && ts_service=OFF || ts_service=ON
- setconfig ts_service "$ts_service"
- else
- echo -e "\033[31m请先设置秘钥!\033[0m"
- sleep 1
- fi
- set_tailscale
- ;;
- 2)
- read -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"
- set_tailscale
- ;;
- 3)
- [ "$ts_subnet" = true ] && ts_subnet=false || ts_subnet=true
- setconfig ts_subnet "$ts_subnet" "$GT_CFG_PATH"
- set_tailscale
- ;;
- 4)
- [ "$ts_exit_node" = true ] && ts_exit_node=false || {
- ts_exit_node=true
- echo -e "\033[31m注意:\033[0m目前exitnode的官方DNS有bug,要么启用域名嗅探并禁用TailscaleDNS,\n要么必须在网页设置Globalname servers为分配的本设备子网IP且启用override"
- sleep 3
- }
- setconfig ts_exit_node "$ts_exit_node" "$GT_CFG_PATH"
- set_tailscale
- ;;
- 5)
- read -p "请输入希望在Tailscale显示的设备名称 > " ts_hostname
- setconfig ts_hostname "$ts_hostname" "$GT_CFG_PATH"
- set_tailscale
- ;;
- *) errornum ;;
- esac
-}
-set_wireguard(){
- [ -n "$wg_public_key" ] && wgp_key_info='*********' || unset wgp_key_info
- [ -n "$wg_private_key" ] && wgv_key_info='*********' || unset wgv_key_info
- [ -n "$wg_pre_shared_key" ] && wgpsk_key_info='*********' || unset wgpsk_key_info
- echo "-----------------------------------------------"
- echo -e "\033[31m注意:\033[0m脚本默认内核为了节约内存没有编译WireGuard模块\n如需使用请先前往自定义内核更新完整版内核文件!"
- echo "-----------------------------------------------"
- echo -e " 1 \033[32m启用/关闭\033[0mWireguard服务 \033[32m$wg_service\033[0m"
- echo "-----------------------------------------------"
- echo -e " 2 设置\033[36mEndpoint地址\033[0m: \033[36m$wg_server\033[0m"
- echo -e " 3 设置\033[36mEndpoint端口\033[0m: \033[36m$wg_port\033[0m"
- echo -e " 4 设置\033[36m公钥-PublicKey\033[0m: \033[36m$wgp_key_info\033[0m"
- echo -e " 5 设置\033[36m密钥-PresharedKey\033[0m: \033[36m$wgpsk_key_info\033[0m"
- echo "-----------------------------------------------"
- echo -e " 6 设置\033[33m私钥-PrivateKey\033[0m: \033[33m$wgv_key_info\033[0m"
- echo -e " 7 设置\033[33m组网IPV4地址\033[0m: \033[33m$wg_ipv4\033[0m"
- echo -e " 8 可选\033[33m组网IPV6地址\033[0m: \033[33m$wg_ipv6\033[0m"
- echo -e " 0 返回上级菜单 \033[0m"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0) ;;
- 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
- echo -e "\033[31m请先完成必选设置!\033[0m"
- sleep 1
- fi
- set_wireguard
- ;;
- [1-8])
- read -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
- set_wireguard
- ;;
- *) errornum ;;
- esac
+ )
+ vms_link="vmess://$(gen_base64 "$vms_json")"
+ line_break
+ echo -e "$GW_SHARE_LINK_HINT\n\033[32m$vms_link\033[0m"
+ sleep 1
+ else
+ msg_alert "\033[31m$GW_FILL_REQUIRED\033[0m"
+ fi
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
}
+set_shadowsocks() {
+ while true; do
+ comp_box "\033[31m$GW_WARN\033[0m" \
+ "$GW_INBOUND_WARN_PORT" \
+ "$GW_INBOUND_WARN_BASIC" \
+ "\033[31m$GW_INBOUND_WARN_ILLEGAL\033[0m"
+ content_line "1) \033[32m$GW_SS_TOGGLE\033[0m \033[32m$sss_service\033[0m"
+ content_line "2) $GW_SET_LISTEN_PORT \033[36m$sss_port\033[0m"
+ content_line "3) $GW_SS_SELECT_CIPHER \033[33m$sss_cipher\033[0m"
+ content_line "4) $GW_SS_SET_PWD \033[36m$sss_pwd\033[0m"
+ gen_base64 1 >/dev/null 2>&1 &&
+ content_line "5) $GW_GEN_SHARE_LINK"
+ btm_box "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " 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
+ msg_alert "\033[31m$GW_FILL_REQUIRED\033[0m"
+ fi
+ fi
+ ;;
+ 2)
+ line_break
+ read -r -p "$GW_INPUT_PORT_DEL0> " text
+ if [ "$text" = 0 ]; then
+ sss_port=''
+ setconfig sss_port "" "$GT_CFG_PATH"
+ elif check_port "$text"; then
+ if echo "|$mix_port|$redir_port|$dns_port|$db_port|" | grep -q "|$text|"; then
+ msg_alert "\033[31m$CHECK_PORT_DUP_ERR\033[0m"
+ sleep 1
+ else
+ sss_port="$text"
+ setconfig sss_port "$text" "$GT_CFG_PATH"
+ fi
+ else
+ sleep 1
+ fi
+ ;;
+ 3)
+ comp_box "$GW_SS_SELECT_CIPHER"
+ 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 "$GW_SS_2022_NOTE_HEADER"
+ content_line "$GW_SS_2022_REQUIRE"
+ 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"
+ }
+ btm_box "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " 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
+ ;;
+ esac
+ setconfig sss_cipher "$sss_cipher" "$GT_CFG_PATH"
+ setconfig sss_pwd "$sss_pwd" "$GT_CFG_PATH"
+ ;;
+ 4)
+ if echo "$sss_cipher" | grep -q '2022-blake3'; then
+ msg_alert "\033[31m$GW_WARN\033[0m$GW_SS_2022_PASSWORD_ONLY"
+ else
+ line_break
+ read -r -p "$GW_INPUT_PWD_DEL0> " text
+ [ "$text" = 0 ] && sss_pwd='' || sss_pwd="$text"
+ setconfig sss_pwd "$text" "$GT_CFG_PATH"
+ fi
+ ;;
+ 5)
+ line_break
+ read -r -p "$GW_INPUT_HOST> " 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 "$GW_SHARE_LINK_HINT\n\033[32m$ss_link\033[0m"
+ sleep 1
+ else
+ msg_alert "\033[31m$GW_FILL_REQUIRED\033[0m"
+ fi
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
+}
+
+# 自定义端点
+set_tailscale() {
+ while true; do
+ [ -n "$ts_auth_key" ] && ts_auth_key_info='*********'
+ comp_box "\033[31m$GW_WARN\033[0m$GW_TS_WARN" \
+ "$GW_TS_KEY_URL" \
+ "$GW_TS_ALLOW_URL" \
+ "$GW_TS_SUBNET_EXIT_HINT"
+ btm_box "1) \033[32m$GW_TS_TOGGLE\033[0m \033[32m$ts_service\033[0m" \
+ "2) $GW_TS_SET_AUTHKEY $ts_auth_key_info" \
+ "3) $GW_TS_SUBNET \033[36m$ts_subnet\033[0m" \
+ "4) $GW_TS_EXIT_NODE \033[36m$ts_exit_node\033[0m" \
+ "5) $GW_TS_HOSTNAME $ts_hostname" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " 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
+ msg_alert "\033[31m$GW_TS_SET_KEY_FIRST\033[0m"
+ fi
+ ;;
+ 2)
+ line_break
+ read -r -p "$GW_TS_INPUT_KEY> " 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
+ msg_alert -t 3 "\033[31m$GW_WARN\033[0m$GW_TS_EXITNODE_WARN"
+ fi
+ setconfig ts_exit_node "$ts_exit_node" "$GT_CFG_PATH"
+ ;;
+ 5)
+ comp_box "\033[36m$GW_TS_INPUT_NAME\033[0m" \
+ "$GW_INPUT_0_BACK"
+ read -r -p "$GW_INPUT_PLAIN> " ts_hostname
+ if [ "$ts_hostname" != 0 ]; then
+ setconfig ts_hostname "$ts_hostname" "$GT_CFG_PATH"
+ fi
+ ;;
+ *)
+ errornum
+ ;;
+ 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
+ comp_box "\033[31m$GW_WARN\033[0m$GW_WG_WARN"
+ btm_box "1) \033[32m$GW_WG_TOGGLE\033[0m \033[32m$wg_service\033[0m" \
+ "" \
+ "2) $GW_WG_SET_ENDPOINT \033[36m$wg_server\033[0m" \
+ "3) $GW_WG_SET_ENDPOINT_PORT \033[36m$wg_port\033[0m" \
+ "4) $GW_WG_SET_PUBLIC \033[36m$wgp_key_info\033[0m" \
+ "5) $GW_WG_SET_PRESHARED \033[36m$wgpsk_key_info\033[0m" \
+ "" \
+ "6) $GW_WG_SET_PRIVATE \033[33m$wgv_key_info\033[0m" \
+ "7) $GW_WG_SET_IPV4 \033[33m$wg_ipv4\033[0m" \
+ "8) $GW_WG_SET_IPV6 \033[33m$wg_ipv6\033[0m" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " 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
+ msg_alert "\033[31m$GW_FILL_REQUIRED\033[0m"
+ fi
+ ;;
+ [1-8])
+ line_break
+ read -r -p "$GW_INPUT_TEXT_DEL0> " 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
+ ;;
+ esac
+ done
+}
diff --git a/scripts/menus/8_tools.sh b/scripts/menus/8_tools.sh
index 89550d67..ad1c0f7c 100644
--- a/scripts/menus/8_tools.sh
+++ b/scripts/menus/8_tools.sh
@@ -6,204 +6,202 @@ __IS_MODULE_8_TOOLS_LOADED=1
. "$CRASHDIR"/libs/logger.sh
. "$CRASHDIR"/libs/web_get_bin.sh
+load_lang 8_tools
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
+ 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
- echo "-----------------------------------------------"
- echo -e "\033[33m此功能仅针对使用Openwrt系统的设备生效,且不依赖服务\033[0m"
- echo -e "\033[31m本功能不支持红米AX6S等镜像化系统设备,请勿尝试!\033[0m"
- echo "-----------------------------------------------"
- echo -e " 1 \033[32m修改\033[0m外网访问端口:\033[36m$ssh_port\033[0m"
- echo -e " 2 \033[32m修改\033[0mSSH访问密码(请连续输入2次后回车)"
- echo -e " 3 \033[33m$ssh_ol\033[0m外网访问SSH"
- echo "-----------------------------------------------"
- echo -e " 0 返回上级菜单 \033[0m"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- ""|0)
- break
- ;;
- 1)
- read -p "请输入端口号(1000-65535) > " num
- if [ -z "$num" ]; then
- errornum
- elif [ $num -gt 65535 -o $num -le 999 ]; then
- echo -e "\033[31m输入错误!请输入正确的数值(1000-65535)!\033[0m"
- elif [ -n "$(netstat -ntul | grep :$num)" ]; then
- echo -e "\033[31m当前端口已被其他进程占用,请重新输入!\033[0m"
- else
- ssh_port=$num
- setconfig ssh_port $ssh_port
- sed -i "/启用外网访问SSH服务/d" /etc/firewall.user
- stop_iptables
- echo -e "\033[32m设置成功,请重新开启外网访问SSH功能!!!\033[0m"
- fi
- sleep 1
- ;;
- 2)
- passwd
- sleep 1
- ;;
- 3)
- 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
- echo "-----------------------------------------------"
- echo -e "已开启外网访问SSH功能!"
- else
- sed -i "/启用外网访问SSH服务/d" /etc/firewall.user
- stop_iptables
- echo "-----------------------------------------------"
- echo -e "已禁止外网访问SSH!"
- fi
- break
- ;;
- *)
- errornum
- sleep 1
- break
- ;;
- esac
- done
+ while true; do
+ [ -n "$(cat /etc/firewall.user 2>&1 | grep '启用外网访问SSH服务')" ] && ssh_ol=$TOOLS_SSH_DISABLE || ssh_ol=$TOOLS_SSH_ENABLE
+ [ -z "$ssh_port" ] && ssh_port=10022
+ comp_box "\033[33m$TOOLS_SSH_ONLY_OPENWRT\033[0m" \
+ "\033[31m$TOOLS_SSH_UNSUPPORTED_SYSTEM\033[0m"
+ btm_box "${TOOLS_SSH_PORT_ITEM_PREFIX}\033[36m$ssh_port\033[0m${TOOLS_SSH_PORT_ITEM_SUFFIX}" \
+ "$TOOLS_SSH_PASS_ITEM" \
+ "${TOOLS_SSH_TOGGLE_ITEM_PREFIX}\033[33m$ssh_ol\033[0m${TOOLS_SSH_TOGGLE_ITEM_SUFFIX}" \
+ "" \
+ "0) $COMMON_BACK \033[0m"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ line_break
+ read -r -p "$TOOLS_PROMPT_PORT" num
+ if [ -z "$num" ]; then
+ errornum
+ elif [ "$num" -gt 65535 ] || [ "$num" -le 999 ]; then
+ msg_alert "\033[31m$TOOLS_ERR_PORT\033[0m"
+ elif [ -n "$(netstat -ntul | grep :$num)" ]; then
+ msg_alert "\033[31m$TOOLS_ERR_PORT_OCCUPIED\033[0m"
+ else
+ ssh_port=$num
+ setconfig ssh_port "$ssh_port"
+ sed -i "/启用外网访问SSH服务/d" /etc/firewall.user
+ stop_iptables
+
+ msg_alert "\033[32m$TOOLS_SSH_SET_OK"
+ fi
+ ;;
+ 2)
+ passwd
+ sleep 1
+ ;;
+ 3)
+ if [ "$ssh_ol" = "$TOOLS_SSH_ENABLE" ]; 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
+ comp_box "$TOOLS_SSH_ENABLED"
+ else
+ sed -i "/启用外网访问SSH服务/d" /etc/firewall.user
+ stop_iptables
+ comp_box "$TOOLS_SSH_DISABLED"
+ fi
+ break
+ ;;
+ *)
+ errornum
+ ;;
+ 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
-
- echo "-----------------------------------------------"
- echo -e "\033[30;47m欢迎使用其他工具菜单:\033[0m"
- echo -e "\033[33m本页工具可能无法兼容全部Linux设备,请酌情使用!\033[0m"
- echo -e "磁盘占用/所在目录:"
- du -sh "$CRASHDIR"
- echo "-----------------------------------------------"
- echo -e " 1 ShellCrash\033[33m测试菜单\033[0m"
- echo -e " 2 ShellCrash\033[32m新手引导\033[0m"
- echo -e " 3 \033[36m日志及推送工具\033[0m"
- [ -f /etc/firewall.user ] && echo -e " 4 \033[32m配置\033[0m外网访问SSH"
- [ -x /usr/sbin/otapredownload ] && echo -e " 5 \033[33m$mi_update\033[0m小米系统自动更新"
- [ "$systype" = "mi_snapshot" ] && echo -e " 6 小米设备软固化SSH ———— \033[$mi_mi_autoSSH_type \033[0m"
- [ "$systype" = "mi_snapshot" ] && echo -e " 8 小米设备Tun模块修复 ———— \033[$mi_tunfix \033[0m"
- echo "-----------------------------------------------"
- echo -e " 0 返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- ""|0)
- break
- ;;
- 1)
- testcommand
- break
- ;;
- 2)
- 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
- echo "-----------------------------------------------"
- echo -e "已\033[33m$mi_update\033[0m小米路由器的自动更新,如未生效,请在官方APP中同步设置!"
- sleep 1
- fi
- ;;
- 6)
- if [ "$systype" = "mi_snapshot" ]; then
- mi_autoSSH
- else
- echo "不支持的设备!"
- fi
- ;;
- 7)
- echo "-----------------------------------------------"
- if [ ! -f "$CRASHDIR"/tools/ShellDDNS.sh ]; then
- echo -e "正在获取在线脚本……"
- 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
- echo -e "\033[31m文件下载失败!\033[0m"
- fi
- else
- . "$CRASHDIR"/tools/ShellDDNS.sh
- fi
- sleep 1
- ;;
- 8)
- if [ -f "$CRASHDIR"/tools/tun.ko ]; then
- read -p "是否禁用此功能并移除相关补丁?(1/0) > " res
- [ "$res" = 1 ] && {
- rm -rf "$CRASHDIR"/tools/tun.ko
- echo -e "\033[33m补丁文件已移除,请立即重启设备以防止出错!\033[0m"
- }
- elif ckcmd modinfo && [ -z "$(modinfo tun)" ]; then
- echo -e "\033[33m本功能需要修改系统文件,不保证没有任何风险!\033[0m"
- echo -e "\033[33m本功能采集的Tun模块并不一定适用于你的设备!\033[0m"
- sleep 1
- read -p "我已知晓,出现问题会自行承担!(1/0) > " res
- if [ "$res" = 1 ]; then
- echo "-----------------------------------------------"
- echo "正在连接服务器获取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 &&
- echo -e "\033[32m设置成功!请重启服务!\033[0m"
- else
- echo -e "\033[31m文件下载失败,请重试!\033[0m"
- fi
- fi
- else
- echo -e "\033[31m当前设备无需设置,请勿尝试!\033[0m"
- sleep 1
- fi
- ;;
- *)
- errornum
- sleep 1
- break
- ;;
- esac
- done
+ while true; do
+ # 获取设置默认显示
+ grep -qE "^\s*[^#].*otapredownload" /etc/crontabs/root >/dev/null 2>&1 && mi_update=$TOOLS_DISABLE || mi_update=$TOOLS_ENABLE
+ [ "$mi_mi_autoSSH" = "$TOOLS_CONFIGURED" ] && mi_mi_autoSSH_type=32m$TOOLS_CONFIGURED || mi_mi_autoSSH_type=31m$COMMON_UNSET
+ [ -f "$CRASHDIR"/tools/tun.ko ] && mi_tunfix=32mON || mi_tunfix=31mOFF
+ comp_box "\033[30;47m$TOOLS_TITLE\033[0m" \
+ "" \
+ "\033[33m$TOOLS_WARN_COMPAT\033[0m" \
+ "$TOOLS_DISK_USAGE" \
+ "$(du -sh "$CRASHDIR")"
+ content_line "$TOOLS_MENU_TEST_ITEM"
+ content_line "$TOOLS_MENU_GUIDE_ITEM"
+ content_line "$TOOLS_MENU_LOG_ITEM"
+ [ -f /etc/firewall.user ] && content_line "$TOOLS_MENU_SSH_ITEM"
+ [ -x /usr/sbin/otapredownload ] && content_line "${TOOLS_MENU_MI_UPDATE_ITEM_PREFIX}\033[33m$mi_update\033[0m${TOOLS_MENU_MI_UPDATE_ITEM_SUFFIX}"
+ [ "$systype" = "mi_snapshot" ] && content_line "${TOOLS_MENU_MI_AUTO_SSH_ITEM_PREFIX}\033[$mi_mi_autoSSH_type \033[0m${TOOLS_MENU_MI_AUTO_SSH_ITEM_SUFFIX}"
+ [ "$systype" = "mi_snapshot" ] && content_line "${TOOLS_MENU_MI_TUN_FIX_ITEM_PREFIX}\033[$mi_tunfix \033[0m${TOOLS_MENU_MI_TUN_FIX_ITEM_SUFFIX}"
+ btm_box "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " 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" = "$TOOLS_DISABLE" ]; 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
+ [ "$mi_update" = "$TOOLS_DISABLE" ] && mi_update=$TOOLS_ENABLE || mi_update=$TOOLS_DISABLE
+ msg_alert "\033[32m${TOOLS_MI_UPDATE_MSG_PREFIX}\033[33m$mi_update\033[0m${TOOLS_MI_UPDATE_MSG_SUFFIX}\033[0m"
+ fi
+ ;;
+ 6)
+ if [ "$systype" = "mi_snapshot" ]; then
+ mi_autoSSH
+ else
+ msg_alert "\033[31m$TOOLS_UNSUPPORTED_DEVICE"
+ fi
+ ;;
+ 7)
+ line_break
+ separator_line "="
+ if [ ! -f "$CRASHDIR"/tools/ShellDDNS.sh ]; then
+ content_line "$TOOLS_FETCHING_SCRIPT"
+ 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$TOOLS_DOWNLOAD_FAIL\033[0m"
+ separator_line "="
+ fi
+ else
+ . "$CRASHDIR"/tools/ShellDDNS.sh
+ fi
+ sleep 1
+ ;;
+ 8)
+ if [ -f "$CRASHDIR"/tools/tun.ko ]; then
+ comp_box "$TOOLS_DISABLE_FIX_CONFIRM"
+ btm_box "$TOOLS_YES" \
+ "$TOOLS_NO_BACK"
+ read -r -p "$TOOLS_SELECT_PROMPT" res
+ [ "$res" = 1 ] && {
+ rm -rf "$CRASHDIR"/tools/tun.ko
+ msg_alert "\033[33m$TOOLS_PATCH_REMOVED\033[0m"
+ }
+ elif ckcmd modinfo && [ -z "$(modinfo tun)" ]; then
+ comp_box "\033[33m$TOOLS_TUN_WARN1\033[0m" \
+ "\033[33m$TOOLS_TUN_WARN2\033[0m"
+ btm_box "$TOOLS_ACCEPT_RISK" \
+ "0) $COMMON_BACK"
+ read -r -p "$TOOLS_SELECT_PROMPT" res
+ if [ "$res" = 1 ]; then
+ line_break
+ separator_line "="
+ content_line "$TOOLS_TUN_CONNECTING"
+ 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$TOOLS_TUN_OK\033[0m"
+ else
+ content_line "\033[31m$TOOLS_TUN_FAIL\033[0m"
+ fi
+ separator_line "="
+ else
+ continue
+ fi
+ else
+ msg_alert "\033[31m$TOOLS_DEVICE_NOT_NEED\033[0m"
+ fi
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
}
mi_autoSSH() {
- echo "-----------------------------------------------"
- echo -e "\033[33m本功能使用软件命令进行固化不保证100%成功!\033[0m"
- echo -e "\033[33m如有问题请加群反馈:\033[36;4mhttps://t.me/ShellClash\033[0m"
- read -p "请输入需要还原的SSH密码(不影响当前密码,回车可跳过) > " mi_mi_autoSSH_pwd
- mi_mi_autoSSH=已配置
+ comp_box "\033[33m$TOOLS_AUTO_SSH_WARN1\033[0m" \
+ "\033[33m$TOOLS_AUTO_SSH_WARN2\033[36;4mhttps://t.me/ShellClash\033[0m"
+ btm_box "$TOOLS_AUTO_SSH_PWD_HINT1" \
+ "$TOOLS_AUTO_SSH_PWD_HINT2"
+ read -r -p "$TOOLS_AUTO_SSH_INPUT" mi_mi_autoSSH_pwd
+ mi_mi_autoSSH=$TOOLS_CONFIGURED
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 && {
@@ -213,596 +211,559 @@ mi_autoSSH() {
nvram set boot_wait=on
nvram commit
}
- echo -e "\033[32m设置成功!\033[0m"
setconfig mi_mi_autoSSH $mi_mi_autoSSH
- setconfig mi_mi_autoSSH_pwd $mi_mi_autoSSH_pwd
- sleep 1
+ setconfig mi_mi_autoSSH_pwd "$mi_mi_autoSSH_pwd"
+ msg_alert "\033[32m$COMMON_SUCCESS\033[0m"
}
-#日志菜单
+# 日志菜单
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未设置
- echo "-----------------------------------------------"
- echo -e " 1 Telegram推送 ——\033[$stat_TG\033[0m"
- echo -e " 2 PushDeer推送 ——\033[$stat_Deer\033[0m"
- echo -e " 3 Bark推送-IOS ——\033[$stat_bark\033[0m"
- echo -e " 4 Passover推送 ——\033[$stat_Po\033[0m"
- echo -e " 5 PushPlus推送 ——\033[$stat_PP\033[0m"
- echo -e " 6 SynoChat推送 ——\033[$stat_SynoChat\033[0m"
- echo -e " 7 Gotify推送 ——\033[$stat_Gotify\033[0m"
- echo "-----------------------------------------------"
- echo -e " a 查看\033[36m运行日志\033[0m"
- echo -e " b 推送任务日志 ——\033[$stat_task\033[0m"
- echo -e " c 设置设备名称 ——\033[$device_s\033[0m"
- echo -e " d 清空日志文件"
- echo "-----------------------------------------------"
- echo -e " 0 返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- ""|0)
- break
- ;;
- 1)
- echo "-----------------------------------------------"
- if [ -n "$push_TG" ]; then
- read -p "确认关闭TG日志推送?(1/0) > " res
- [ "$res" = 1 ] && {
- push_TG=
- chat_ID=
- setconfig push_TG
- setconfig chat_ID
- }
- else
- #echo -e "\033[33m详细设置指南请参考 https://juewuy.github.io/ \033[0m"
- . "$CRASHDIR"/menus/bot_tg_bind.sh
- chose_bot() {
- echo "-----------------------------------------------"
- echo -e " 1 使用公共机器人 ——不依赖内核服务"
- echo -e " 2 使用私人机器人 ——需要额外申请"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case $num in
- 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
- sleep 1
- ;;
- 2)
- echo "-----------------------------------------------"
- if [ -n "$push_Deer" ]; then
- read -p "确认关闭PushDeer日志推送?(1/0) > " res
- [ "$res" = 1 ] && {
- push_Deer=
- setconfig push_Deer
- }
- else
- #echo -e "\033[33m详细设置指南请参考 https://juewuy.github.io/ \033[0m"
- echo -e "请先前往 \033[32;4mhttp://www.pushdeer.com/official.html\033[0m 扫码安装快应用或下载APP"
- echo -e "打开快应用/APP,并完成登陆"
- echo -e "\033[33m切换到「设备」标签页,点击右上角的加号,注册当前设备\033[0m"
- echo -e "\033[36m切换到「秘钥」标签页,点击右上角的加号,创建一个秘钥,并复制\033[0m"
- echo "-----------------------------------------------"
- read -p "请输入你复制的秘钥 > " url
- if [ -n "$url" ]; then
- push_Deer=$url
- setconfig push_Deer $url
- logger "已完成PushDeer日志推送设置!" 32
- else
- echo -e "\033[31m输入错误,请重新输入!\033[0m"
- fi
- sleep 1
- fi
- ;;
- 3)
- echo "-----------------------------------------------"
- if [ -n "$push_bark" ]; then
- read -p "确认关闭Bark日志推送?(1/0) > " res
- [ "$res" = 1 ] && {
- push_bark=
- bark_param=
- setconfig push_bark
- setconfig bark_param
- }
- else
- #echo -e "\033[33m详细设置指南请参考 https://juewuy.github.io/ \033[0m"
- echo -e "\033[33mBark推送仅支持IOS系统,其他平台请使用其他推送方式!\033[0m"
- echo -e "\033[32m请安装Bark-IOS客户端,并在客户端中找到专属推送链接\033[0m"
- echo "-----------------------------------------------"
- read -p "请输入你的Bark推送链接 > " url
- if [ -n "$url" ]; then
- push_bark=$url
- setconfig push_bark $url
- logger "已完成Bark日志推送设置!" 32
- else
- echo -e "\033[31m输入错误,请重新输入!\033[0m"
- fi
- sleep 1
- fi
- ;;
- 4)
- echo "-----------------------------------------------"
- if [ -n "$push_Po" ]; then
- read -p "确认关闭Pushover日志推送?(1/0) > " res
- [ "$res" = 1 ] && {
- push_Po=
- push_Po_key=
- setconfig push_Po
- setconfig push_Po_key
- }
- else
- #echo -e "\033[33m详细设置指南请参考 https://juewuy.github.io/ \033[0m"
- echo -e "请先通过 \033[32;4mhttps://pushover.net/\033[0m 注册账号并获取\033[36mUser Key\033[0m"
- echo "-----------------------------------------------"
- read -p "请输入你的User Key > " key
- if [ -n "$key" ]; then
- echo "-----------------------------------------------"
- echo -e "\033[33m请检查注册邮箱,完成账户验证\033[0m"
- read -p "我已经验证完成(1/0) > "
- echo "-----------------------------------------------"
- echo -e "请通过 \033[32;4mhttps://pushover.net/apps/build\033[0m 生成\033[36mAPI Token\033[0m"
- echo "-----------------------------------------------"
- read -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
- echo -e "\033[31m输入错误,请重新输入!\033[0m"
- fi
- else
- echo -e "\033[31m输入错误,请重新输入!\033[0m"
- fi
- fi
- sleep 1
- ;;
- 5)
- echo "-----------------------------------------------"
- if [ -n "$push_PP" ]; then
- read -p "确认关闭PushPlus日志推送?(1/0) > " res
- [ "$res" = 1 ] && {
- push_PP=
- setconfig push_PP
- }
- else
- #echo -e "\033[33m详细设置指南请参考 https://juewuy.github.io/ \033[0m"
- echo -e "请先通过 \033[32;4mhttps://www.pushplus.plus/push1.html\033[0m 注册账号并获取\033[36mtoken\033[0m"
- echo "-----------------------------------------------"
- read -p "请输入你的token > " Token
- if [ -n "$Token" ]; then
- push_PP=$Token
- setconfig push_PP $Token
- logger "已完成PushPlus日志推送设置!" 32
- else
- echo -e "\033[31m输入错误,请重新输入!\033[0m"
- fi
- fi
- sleep 1
- ;;
- 6)
- echo "-----------------------------------------------"
- if [ -n "$push_SynoChat" ]; then
- read -p "确认关闭SynoChat日志推送?(1/0) > " res
- [ "$res" = 1 ] && {
- push_SynoChat=
- setconfig push_SynoChat
- }
- else
- echo "-----------------------------------------------"
- read -p "请输入你的Synology DSM主页地址 > " URL
- echo "-----------------------------------------------"
- read -p "请输入你的Synology Chat Token > " TOKEN
- echo "-----------------------------------------------"
- echo -e '请通过"你的群晖地址/webapi/entry.cgi?api=SYNO.Chat.External&method=user_list&version=2&token=你的TOKEN"获取user_id'
- echo "-----------------------------------------------"
- read -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
- echo -e "\033[31m输入错误,请重新输入!\033[0m"
- setconfig push_ChatURL
- setconfig push_ChatTOKEN
- setconfig push_ChatUSERID
- push_SynoChat=
- setconfig push_SynoChat
- fi
- fi
- sleep 1
- ;;
- # 在menu.sh的case $num in代码块中添加
- 7)
- echo "-----------------------------------------------"
- if [ -n "$push_Gotify" ]; then
- read -p "确认关闭Gotify日志推送?(1/0) > " res
- [ "$res" = 1 ] && {
- push_Gotify=
- setconfig push_Gotify
- }
- else
- echo -e "请先通过Gotify服务器获取推送URL"
- echo -e "格式示例: https://gotify.example.com/message?token=你的应用令牌"
- echo "-----------------------------------------------"
- read -p "请输入你的Gotify推送URL > " url
- if [ -n "$url" ]; then
- push_Gotify=$url
- setconfig push_Gotify "$url"
- logger "已完成Gotify日志推送设置!" 32
- else
- echo -e "\033[31m输入错误,请重新输入!\033[0m"
- fi
- fi
- sleep 1
- ;;
- a)
- if [ -s "$TMPDIR"/ShellCrash.log ]; then
- echo "-----------------------------------------------"
- cat "$TMPDIR"/ShellCrash.log
- exit 0
- else
- echo -e "\033[31m未找到相关日志!\033[0m"
- fi
- sleep 1
- break
- ;;
- b)
- [ "$task_push" = 1 ] && task_push='' || task_push=1
- setconfig task_push $task_push
- sleep 1
- ;;
- c)
- read -p "请输入本设备自定义推送名称 > " device_name
- setconfig device_name $device_name
- sleep 1
- ;;
- d)
- echo -e "\033[33m运行日志及任务日志均已清空!\033[0m"
- rm -rf "$TMPDIR"/ShellCrash.log
- sleep 1
- ;;
- *)
- errornum
- sleep 1
- break
- ;;
- esac
- done
+ 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$COMMON_UNSET
+ comp_box "${TOOLS_LOG_TG_PREFIX}\033[$stat_TG\033[0m${TOOLS_LOG_TG_SUFFIX}" \
+ "${TOOLS_LOG_DEER_PREFIX}\033[$stat_Deer\033[0m${TOOLS_LOG_DEER_SUFFIX}" \
+ "${TOOLS_LOG_BARK_PREFIX}\033[$stat_bark\033[0m${TOOLS_LOG_BARK_SUFFIX}" \
+ "${TOOLS_LOG_PO_PREFIX}\033[$stat_Po\033[0m${TOOLS_LOG_PO_SUFFIX}" \
+ "${TOOLS_LOG_PP_PREFIX}\033[$stat_PP\033[0m${TOOLS_LOG_PP_SUFFIX}" \
+ "${TOOLS_LOG_SYNO_PREFIX}\033[$stat_SynoChat\033[0m${TOOLS_LOG_SYNO_SUFFIX}" \
+ "${TOOLS_LOG_GOTIFY_PREFIX}\033[$stat_Gotify\033[0m${TOOLS_LOG_GOTIFY_SUFFIX}" \
+ "" \
+ "$TOOLS_LOG_VIEW" \
+ "${TOOLS_LOG_TASK_PREFIX}\033[$stat_task\033[0m${TOOLS_LOG_TASK_SUFFIX}" \
+ "${TOOLS_LOG_DEVICE_PREFIX}\033[$device_s\033[0m${TOOLS_LOG_DEVICE_SUFFIX}" \
+ "$TOOLS_LOG_CLEAR" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ if [ -n "$push_TG" ]; then
+ comp_box "$TOOLS_CONFIRM_CLOSE_TG"
+ btm_box "$TOOLS_YES" \
+ "$TOOLS_NO_BACK"
+ read -r -p "$TOOLS_SELECT_PROMPT" 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() {
+ comp_box "$TOOLS_BOT_PUBLIC" \
+ "$TOOLS_BOT_PRIVATE" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " 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)
+ if [ -n "$push_Deer" ]; then
+ comp_box "$TOOLS_CONFIRM_CLOSE_DEER"
+ btm_box "$TOOLS_YES" \
+ "$TOOLS_NO_BACK"
+ read -r -p "$TOOLS_SELECT_PROMPT" res
+ if [ "$res" = 1 ]; then
+ push_Deer=
+ push_Deer_url=
+ setconfig push_Deer
+ setconfig push_Deer_url
+ else
+ continue
+ fi
+ else
+ # echo -e "\033[33m详细设置指南请参考 https://juewuy.github.io/ \033[0m"
+ comp_box "$TOOLS_PUSHDEER_SELECT_SERVER" \
+ "$TOOLS_PUSHDEER_OFFICIAL" \
+ "$TOOLS_PUSHDEER_CUSTOM" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$TOOLS_SELECT_PROMPT" num
+ case "$num" in
+ 0)
+ continue
+ ;;
+ 2)
+ comp_box "$TOOLS_PUSHDEER_CUSTOM_URL_HINT" \
+ "$TOOLS_PUSHDEER_CUSTOM_URL_EXAMPLE"
+ btm_box "\033[36m$TOOLS_PUSHDEER_CUSTOM_URL_INPUT\033[0m" \
+ "$TOOLS_OR_BACK"
+ read -r -p "$TOOLS_AUTO_SSH_INPUT" url
+ if [ "$url" = 0 ]; then
+ continue
+ elif [ -z "$url" ]; then
+ msg_alert "\033[31m$COMMON_ERR_INPUT\033[0m"
+ continue
+ fi
+ push_Deer_url=${url%/}
+ setconfig push_Deer_url "${url%/}"
+ ;;
+ 1)
+ push_Deer_url=
+ setconfig push_Deer_url
+ ;;
+ *)
+ errornum
+ continue
+ ;;
+ esac
+ comp_box "$TOOLS_PUSHDEER_INSTALL1" \
+ "$TOOLS_PUSHDEER_INSTALL2" \
+ "$TOOLS_PUSHDEER_INSTALL3" \
+ "$TOOLS_PUSHDEER_INSTALL4"
+ btm_box "\033[36m$TOOLS_PUSHDEER_SECRET_HINT\033[0m" \
+ "$TOOLS_OR_BACK"
+ read -r -p "$TOOLS_AUTO_SSH_INPUT" url
+ if [ "$url" = 0 ]; then
+ continue
+ elif [ -n "$url" ]; then
+ push_Deer=$url
+ setconfig push_Deer "$url"
+ logger "$TOOLS_PUSHDEER_OK" 32
+ else
+ msg_alert "\033[31m$COMMON_ERR_INPUT\033[0m"
+ fi
+ fi
+ ;;
+ 3)
+ if [ -n "$push_bark" ]; then
+ comp_box "$TOOLS_CONFIRM_CLOSE_BARK"
+ btm_box "$TOOLS_YES" \
+ "$TOOLS_NO_BACK"
+ read -r -p "$TOOLS_SELECT_PROMPT" 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"
+ comp_box "\033[33m$TOOLS_BARK_WARN\033[0m" \
+ "\033[32m$TOOLS_BARK_INSTALL\033[0m"
+ btm_box "\033[36m$TOOLS_BARK_URL_HINT\033[0m" \
+ "$TOOLS_OR_BACK"
+ read -r -p "$TOOLS_AUTO_SSH_INPUT" url
+ if [ "$url" = 0 ]; then
+ continue
+ elif [ -n "$url" ]; then
+ push_bark=$url
+ setconfig push_bark "$url"
+ logger "$TOOLS_BARK_OK" 32
+ else
+ msg_alert "\033[31m$COMMON_ERR_INPUT\033[0m"
+ fi
+ fi
+ ;;
+ 4)
+ if [ -n "$push_Po" ]; then
+ comp_box "$TOOLS_CONFIRM_CLOSE_PO"
+ btm_box "$TOOLS_YES" \
+ "$TOOLS_NO_BACK"
+ read -r -p "$TOOLS_SELECT_PROMPT" 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"
+ comp_box "$TOOLS_PUSHOVER_REG" \
+ "" \
+ "\033[36m$TOOLS_PUSHOVER_USERKEY_HINT\033[0m" \
+ "$TOOLS_OR_BACK"
+ read -r -p "$TOOLS_AUTO_SSH_INPUT" key
+ if [ "$key" = 0 ]; then
+ continue
+ elif [ -n "$key" ]; then
+ comp_box "\033[33m$TOOLS_PUSHOVER_VERIFY\033[0m"
+ btm_box "$TOOLS_PUSHOVER_VERIFIED" \
+ "0) $COMMON_BACK"
+ read -r -p "$TOOLS_PUSHOVER_VERIFY_PROMPT" res
+ if [ "$res" = 1 ]; then
+ comp_box "$TOOLS_PUSHOVER_TOKEN_BUILD"
+ read -r -p "$TOOLS_PUSHOVER_TOKEN_HINT> " Token
+ if [ -n "$Token" ]; then
+ push_Po=$Token
+ push_Po_key=$key
+ setconfig push_Po "$Token"
+ setconfig push_Po_key "$key"
+ logger "$TOOLS_PUSHOVER_OK" 32
+ else
+ msg_alert "\033[31m$COMMON_ERR_INPUT\033[0m"
+ fi
+ else
+ continue
+ fi
+ else
+ msg_alert "\033[31m$COMMON_ERR_INPUT\033[0m"
+ fi
+ fi
+ ;;
+ 5)
+ if [ -n "$push_PP" ]; then
+ comp_box "$TOOLS_CONFIRM_CLOSE_PP"
+ btm_box "$TOOLS_YES" \
+ "$TOOLS_NO_BACK"
+ read -r -p "$TOOLS_SELECT_PROMPT" res
+ if [ "$res" = 1 ]; then
+ push_PP=
+ setconfig push_PP
+ else
+ continue
+ fi
+ else
+ # echo -e "\033[33m详细设置指南请参考 https://juewuy.github.io/ \033[0m"
+ comp_box "$TOOLS_PUSHPLUS_REG"
+ btm_box "\033[36m$TOOLS_PUSHPLUS_TOKEN_HINT\033[0m" \
+ "$TOOLS_OR_BACK"
+ read -r -p "$TOOLS_AUTO_SSH_INPUT" Token
+ if [ "$Token" = 0 ]; then
+ continue
+ elif [ -n "$Token" ]; then
+ push_PP=$Token
+ setconfig push_PP "$Token"
+ logger "$TOOLS_PUSHPLUS_OK" 32
+ else
+ msg_alert "\033[31m$COMMON_ERR_INPUT\033[0m"
+ fi
+ fi
+ ;;
+ 6)
+ if [ -n "$push_SynoChat" ]; then
+ comp_box "$TOOLS_CONFIRM_CLOSE_SYNO"
+ btm_box "$TOOLS_YES" \
+ "$TOOLS_NO_BACK"
+ read -r -p "$TOOLS_SELECT_PROMPT" res
+ if [ "$res" = 1 ]; then
+ push_SynoChat=
+ setconfig push_SynoChat
+ else
+ continue
+ fi
+ else
+ line_break
+ read -r -p "$TOOLS_SYNOCHAT_URL_HINT> " URL
+ read -r -p "$TOOLS_SYNOCHAT_TOKEN_HINT> " TOKEN
+ comp_box "$TOOLS_SYNOCHAT_USERID_HINT"
+ read -r -p "$TOOLS_SYNOCHAT_USERID_INPUT" 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 "$TOOLS_SYNOCHAT_OK" 32
+ else
+ setconfig push_ChatURL
+ setconfig push_ChatTOKEN
+ setconfig push_ChatUSERID
+ push_SynoChat=
+ setconfig push_SynoChat
+
+ msg_alert "\033[31m$COMMON_ERR_INPUT\033[0m"
+ fi
+ fi
+ ;;
+ # 在menu.sh的case $num in代码块中添加
+ 7)
+ if [ -n "$push_Gotify" ]; then
+ comp_box "$TOOLS_CONFIRM_CLOSE_GOTIFY"
+ btm_box "$TOOLS_YES" \
+ "$TOOLS_NO_BACK"
+ read -r -p "$TOOLS_SELECT_PROMPT" res
+ if [ "$res" = 1 ]; then
+ push_Gotify=
+ setconfig push_Gotify
+ else
+ continue
+ fi
+ else
+ comp_box "$TOOLS_GOTIFY_REG" \
+ "$TOOLS_GOTIFY_FORMAT"
+ btm_box "\033[36m$TOOLS_GOTIFY_URL_HINT\033[0m" \
+ "$TOOLS_OR_BACK"
+ read -r -p "$TOOLS_AUTO_SSH_INPUT" url
+ if [ "$url" = 0 ]; then
+ continue
+ elif [ -n "$url" ]; then
+ push_Gotify=$url
+ setconfig push_Gotify "$url"
+ logger "$TOOLS_GOTIFY_OK" 32
+ else
+ msg_alert "\033[31m$COMMON_ERR_INPUT\033[0m"
+ fi
+ fi
+ ;;
+ a)
+ if [ -s "$TMPDIR"/ShellCrash.log ]; then
+ line_break
+ echo "==========================================================="
+ cat "$TMPDIR"/ShellCrash.log
+ echo "==========================================================="
+ exit
+ else
+ msg_alert "\033[31m$TOOLS_LOG_NOT_FOUND\033[0m"
+ fi
+ ;;
+ b)
+ [ "$task_push" = 1 ] && task_push='' || task_push=1
+ setconfig task_push "$task_push"
+ sleep 1
+ ;;
+ c)
+ comp_box "$TOOLS_DEVICE_NAME_HINT" \
+ "$TOOLS_DEVICE_NAME_BACK"
+ read -r -p "$TOOLS_AUTO_SSH_INPUT" device_name
+ if [ -n "$device_name" ]; then
+ setconfig device_name "$device_name"
+ fi
+ ;;
+ d)
+ rm -rf "$TMPDIR"/ShellCrash.log
+ msg_alert "\033[33m$TOOLS_LOG_CLEARED\033[0m"
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
}
-#测试菜单
-testcommand(){
- echo "-----------------------------------------------"
- echo -e "\033[30;47m这里是测试命令菜单\033[0m"
- echo -e "\033[33m如遇问题尽量运行相应命令后截图提交issue或TG讨论组\033[0m"
- echo "-----------------------------------------------"
- echo " 1 Debug模式运行内核"
- echo " 2 查看系统DNS端口(:53)占用 "
- echo " 3 测试ssl加密(aes-128-gcm)跑分"
- echo " 4 查看ShellCrash相关路由规则"
- echo " 5 查看内核配置文件前40行"
- echo " 6 测试代理服务器连通性(google.tw)"
- echo "-----------------------------------------------"
- echo " 0 返回上级目录!"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0)
- main_menu
- ;;
- 1)
- debug
- testcommand
- ;;
- 2)
- echo "-----------------------------------------------"
- netstat -ntulp |grep 53
- echo "-----------------------------------------------"
- echo -e "可以使用\033[44m netstat -ntulp |grep xxx \033[0m来查询任意(xxx)端口"
- exit;
- ;;
- 3)
- echo "-----------------------------------------------"
- openssl speed -multi 4 -evp aes-128-gcm
- echo "-----------------------------------------------"
- exit;
- ;;
- 4)
- 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模式|混合模式')" ] && iptables -t nat -L shellcrash --line-numbers
- [ -n "$(echo $redir_mod | grep -E 'Tproxy模式|混合模式|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模式|混合模式')" ] && iptables -t nat -L shellcrash_out --line-numbers
- [ -n "$(echo $redir_mod | grep -E 'Tproxy模式|混合模式|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模式|混合模式')" ] && ip6tables -t nat -L shellcrashv6 --line-numbers
- }
- [ -n "$(echo $redir_mod | grep -E 'Tproxy模式|混合模式|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
- exit;
- ;;
- 5)
- echo "$crashcore" | grep -q 'singbox' && config_path="$CRASHDIR"/jsons/config.json || config_path="$CRASHDIR"/yamls/config.yaml
- echo "-----------------------------------------------"
- sed -n '1,40p' "$config_path"
- echo "-----------------------------------------------"
- exit;
- ;;
- 6)
- echo "注意:依赖curl(不支持wget),且测试结果不保证一定准确!"
- 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
- echo "-----------------------------------------------"
- if [ `echo ${#delay}` -gt 1 ];then
- echo -e "\033[32m连接成功!响应时间为:"$delay" ms\033[0m"
- else
- echo -e "\033[31m连接超时!请重试或检查节点配置!\033[0m"
- fi
- main_menu
- ;;
- *)
- errornum
- main_menu
- ;;
- esac
-}
-debug(){
- echo "$crashcore" | grep -q 'singbox' && config_tmp="$TMPDIR"/jsons || config_tmp="$TMPDIR"/config.yaml
- echo "-----------------------------------------------"
- echo -e "\033[36m注意:Debug运行均会停止原本的内核服务\033[0m"
- echo -e "后台运行日志地址:\033[32m$TMPDIR/debug.log\033[0m"
- echo -e "如长时间运行后台监测,日志等级推荐error!防止文件过大!"
- echo -e "你也可以通过:\033[33mcrash -s debug 'warning'\033[0m 命令使用其他日志等级"
- echo "-----------------------------------------------"
- echo -e " 1 仅测试\033[32m$config_tmp\033[0m配置文件可用性"
- echo -e " 2 前台运行\033[32m$config_tmp\033[0m配置文件,不配置防火墙劫持(\033[33m使用Ctrl+C手动停止\033[0m)"
- echo -e " 3 后台运行完整启动流程,并配置防火墙劫持,日志等级:\033[31merror\033[0m"
- echo -e " 4 后台运行完整启动流程,并配置防火墙劫持,日志等级:\033[32minfo\033[0m"
- echo -e " 5 后台运行完整启动流程,并配置防火墙劫持,日志等级:\033[33mdebug\033[0m"
- echo -e " 6 后台运行完整启动流程,并配置防火墙劫持,且将错误日志打印到闪存:\033[32m$CRASHDIR/debug.log\033[0m"
- echo "-----------------------------------------------"
- echo -e " 8 后台运行完整启动流程,输出执行错误并查找上下文,之后关闭进程"
- [ -s "$TMPDIR"/jsons/inbounds.json ] && echo -e " 9 将\033[32m$config_tmp\033[0m下json文件合并为$TMPDIR/debug.json"
- echo "-----------------------------------------------"
- echo " 0 返回上级目录!"
- read -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
- echo "-----------------------------------------------"
- exit
- ;;
- 2)
- "$CRASHDIR"/start.sh stop
- "$CRASHDIR"/start.sh bfstart
- $COMMAND
- rm -rf "$TMPDIR"/CrashCore
- echo "-----------------------------------------------"
- 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)
- echo -e "频繁写入闪存会导致闪存寿命降低,如非遇到会导致设备死机或重启的bug,请勿使用此功能!"
- read -p "是否继续?(1/0) > " res
- [ "$res" = 1 ] && "$CRASHDIR"/start.sh debug debug flash
- main_menu
- ;;
- 8)
- $0 -d
- main_menu
- ;;
- 9)
- . "$CRASHDIR"/libs/core_webget.sh && core_find && "$TMPDIR"/CrashCore merge "$TMPDIR"/debug.json -C "$TMPDIR"/jsons && echo -e "\033[32m合并成功!\033[0m"
- [ "$TMPDIR" = "$BINDIR" ] && rm -rf "$TMPDIR"/CrashCore
- main_menu
- ;;
- *)
- errornum
- ;;
- esac
+# 测试菜单
+testcommand() {
+ while true; do
+ comp_box "\033[30;47m$TOOLS_TEST_MENU_TITLE\033[0m" \
+ "\033[33m$TOOLS_TEST_MENU_HINT\033[0m"
+ btm_box "$TOOLS_TEST_ITEM_1" \
+ "$TOOLS_TEST_ITEM_2" \
+ "$TOOLS_TEST_ITEM_3" \
+ "$TOOLS_TEST_ITEM_4" \
+ "$TOOLS_TEST_ITEM_5" \
+ "$TOOLS_TEST_ITEM_6" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ 0)
+ break
+ ;;
+ 1)
+ debug
+ ;;
+ 2)
+ line_break
+ echo "==========================================================="
+ netstat -ntulp | grep 53
+ echo
+ echo -e "$TOOLS_NETSTAT_HINT"
+ echo "==========================================================="
+ ;;
+ 3)
+ line_break
+ openssl speed -multi 4 -evp aes-128-gcm
+ ;;
+ 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 "$TOOLS_FW_TITLE"
+ iptables -L INPUT --line-numbers
+ fi
+ ;;
+ 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"
+ ;;
+ 6)
+ comp_box "\033[33m$TOOLS_PROXY_NOTE\033[0m"
+ 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$TOOLS_PROXY_OK$delay ms\033[0m"
+ else
+ content_line "\033[31m$TOOLS_PROXY_TIMEOUT\033[0m"
+ fi
+ separator_line "="
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
}
-#新手引导
-userguide(){
- . "$CRASHDIR"/libs/check_dir_avail.sh
- forwhat(){
- 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 -p "请输入对应数字 > " num
- case "$num" in
- 1)
- #设置运行模式
- redir_mod="混合模式"
- [ -n "$(echo $cputype | grep -E "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
- }
- #设置开机启动
- [ -f /etc/rc.common -a "$(cat /proc/1/comm)" = "procd" ] && /etc/init.d/shellcrash enable
- 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 -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
- ;;
- 2)
- setconfig redir_mod "Redir模式"
- [ -n "$(echo $cputype | grep -E "linux.*mips.*")" ] && setconfig crashcore "clash"
- setconfig common_ports "OFF"
- setconfig firewall_area '2'
- ;;
- 3)
- mv -f $CFG_PATH.bak $CFG_PATH
- echo -e "\033[32m脚本设置已还原!\033[0m"
- echo -e "\033[33m请重新启动脚本!\033[0m"
- exit 0
- ;;
- *)
- errornum
- forwhat
- ;;
- esac
- }
- 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 -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 -p "是否启用软固化功能?(1/0) > " res
- [ "$res" = 1 ] && mi_autoSSH
- fi
- #提示导入订阅或者配置文件
- [ ! -s "$CRASHDIR"/yamls/config.yaml -a ! -s "$CRASHDIR"/jsons/config.json ] && {
- echo "-----------------------------------------------"
- echo -e "\033[32m是否导入配置文件?\033[0m(这是运行前的最后一步)"
- echo -e "\033[0m你必须拥有一份配置文件才能运行服务!\033[0m"
- echo "-----------------------------------------------"
- read -p "现在开始导入?(1/0) > " res
- [ "$res" = 1 ] && inuserguide=1 && {
- . "$CRASHDIR"/menus/6_core_config.sh && set_core_config
- inuserguide=""
- }
- }
- #回到主界面
- echo "-----------------------------------------------"
- echo -e "\033[36m很好!现在只需要执行启动就可以愉快的使用了!\033[0m"
- echo "-----------------------------------------------"
- read -p "立即启动服务?(1/0) > " res
- [ "$res" = 1 ] && start_core && sleep 2
- return 0
+debug() {
+ rm -f "$CRASHDIR"/\.start_error #移除自启失败标记
+ echo "$crashcore" | grep -q 'singbox' && config_tmp="$TMPDIR"/jsons || config_tmp="$TMPDIR"/config.yaml
+ comp_box "\033[36m$TOOLS_DEBUG_WARN1\033[0m" \
+ "${TOOLS_DEBUG_WARN2_PREFIX}\033[32m$TMPDIR/debug.log\033[0m${TOOLS_DEBUG_WARN2_SUFFIX}" \
+ "$TOOLS_DEBUG_WARN3" \
+ "$TOOLS_DEBUG_WARN4"
+ content_line "${TOOLS_DEBUG_ITEM_1_PREFIX}\033[32m$config_tmp\033[0m${TOOLS_DEBUG_ITEM_1_SUFFIX}"
+ content_line "${TOOLS_DEBUG_ITEM_2_PREFIX}\033[32m$config_tmp\033[0m${TOOLS_DEBUG_ITEM_2_SUFFIX}"
+ content_line "$TOOLS_DEBUG_ITEM_3"
+ content_line "$TOOLS_DEBUG_ITEM_4"
+ content_line "$TOOLS_DEBUG_ITEM_5"
+ content_line "${TOOLS_DEBUG_ITEM_6_PREFIX}\033[32m$CRASHDIR/debug.log\033[0m${TOOLS_DEBUG_ITEM_6_SUFFIX}"
+ content_line ""
+ content_line "$TOOLS_DEBUG_ITEM_8"
+ [ -s "$TMPDIR"/jsons/inbounds.json ] && content_line "${TOOLS_DEBUG_ITEM_9_PREFIX}\033[32m$config_tmp\033[0m${TOOLS_DEBUG_ITEM_9_SUFFIX}\033[32m$TMPDIR/debug.json\033[0m"
+ btm_box "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ 0) ;;
+ 1)
+ "$CRASHDIR"/start.sh stop
+ "$CRASHDIR"/starts/bfstart.sh
+ 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)
+ comp_box "\033[33m$TOOLS_FLASH_WARN\033[0m" \
+ "$TOOLS_FLASH_CONFIRM"
+ btm_box "$TOOLS_YES" \
+ "$TOOLS_NO"
+ read -r -p "$TOOLS_SELECT_PROMPT" res
+ if [ "$res" = 1 ]; then
+ "$CRASHDIR"/start.sh debug debug flash
+ fi
+ main_menu
+ ;;
+ 8)
+ $0 -d
+ main_menu
+ ;;
+ 9)
+ . "$CRASHDIR"/libs/core_tools.sh && core_find && "$TMPDIR"/CrashCore merge "$TMPDIR"/debug.json -C "$TMPDIR"/jsons && line_break
+ comp_box "\033[32m$TOOLS_MERGE_OK\033[0m"
+ [ "$TMPDIR" = "$BINDIR" ] && rm -rf "$TMPDIR"/CrashCore
+ debug
+ ;;
+ *)
+ errornum
+ ;;
+ esac
}
diff --git a/scripts/menus/9_upgrade.sh b/scripts/menus/9_upgrade.sh
index a7f9d804..b887c9c9 100644
--- a/scripts/menus/9_upgrade.sh
+++ b/scripts/menus/9_upgrade.sh
@@ -7,46 +7,43 @@ __IS_MODULE_9_UPGRADE_LOADED=1
. "$CRASHDIR"/libs/check_dir_avail.sh
. "$CRASHDIR"/libs/check_cpucore.sh
. "$CRASHDIR"/libs/web_get_bin.sh
+load_lang 9_upgrade
-error_down(){
- echo -e "\033[33m请尝试切换至其他安装源后重新下载!\033[0m"
- echo -e "或者参考 \033[32;4mhttps://juewuy.github.io/bdaz\033[0m 进行本地安装!"
- sleep 1
+error_down() {
+ btm_box "\033[33m$UPG_ERR_TRY_OTHER_SOURCE\033[0m" \
+ "$UPG_ERR_LOCAL_INSTALL"
+ sleep 1
}
# 更新/卸载功能菜单
upgrade() {
while true; do
- echo "-----------------------------------------------"
- [ -z "$version_new" ] && checkupdate
+ if [ -z "$version_new" ]; then
+ checkupdate
+ fi
[ -z "$core_v" ] && core_v=$crashcore
core_v_new=$(eval echo \$"$crashcore"_v)
- echo -e "\033[30;47m欢迎使用更新功能:\033[0m"
- echo "-----------------------------------------------"
- echo -e "当前目录(\033[32m$CRASHDIR\033[0m)剩余空间:\033[36m$(dir_avail "$CRASHDIR" -h)\033[0m"
+ top_box "\033[30;47m$UPG_TITLE\033[0m" \
+ "" \
+ "$UPG_CUR_DIR_SPACE(\033[32m$CRASHDIR\033[0m):\033[36m$(dir_avail "$CRASHDIR" -h)\033[0m"
[ "$(dir_avail "$CRASHDIR")" -le 5120 ] && [ "$CRASHDIR" = "$BINDIR" ] && {
- echo -e "\033[33m当前目录剩余空间较低,建议开启小闪存模式!\033[0m"
- sleep 1
+ content_line "\033[33m$UPG_LOW_SPACE_HINT\033[0m"
}
- echo "-----------------------------------------------"
- echo -e " 1 更新\033[36m管理脚本 \033[33m$versionsh_l\033[0m > \033[32m$version_new \033[36m$release_type\033[0m"
- echo -e " 2 切换\033[33m内核文件 \033[33m$core_v\033[0m > \033[32m$core_v_new\033[0m"
- echo -e " 3 更新\033[32m数据库文件\033[0m > \033[32m$GeoIP_v\033[0m"
- echo -e " 4 安装本地\033[35mDashboard\033[0m面板"
- echo -e " 5 安装/更新本地\033[33m根证书文件\033[0m"
- echo -e " 6 查看\033[32mPAC\033[0m自动代理配置"
- echo "-----------------------------------------------"
- echo -e " 7 切换\033[36m安装源\033[0m及\033[36m安装版本\033[0m"
- echo -e " 8 \033[32m配置自动更新\033[0m"
- echo -e " 9 \033[31m卸载ShellCrash\033[0m"
- echo "-----------------------------------------------"
- echo -e " 99 \033[36m鸣谢!\033[0m"
- echo "-----------------------------------------------"
- echo -e " 0 返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
+ separator_line "="
+ btm_box "1) $UPG_MENU_SCRIPT\033[36m$UPG_MENU_SCRIPT_NAME\t\033[33m$versionsh_l\033[0m > \033[32m$version_new \033[36m$release_type\033[0m" \
+ "2) $UPG_MENU_CORE\033[33m$UPG_MENU_CORE_NAME\t\033[33m$core_v\033[0m > \033[32m$core_v_new\033[0m" \
+ "3) $UPG_MENU_GEO\033[32m$UPG_MENU_GEO_NAME\033[0m" \
+ "4) $UPG_MENU_DB\033[35m$UPG_MENU_DB_NAME\033[0m" \
+ "5) $UPG_MENU_CRT\033[33m$UPG_MENU_CRT_NAME\033[0m" \
+ "6) \033[32mPAC\033[0m$UPG_MENU_PAC" \
+ "7) $UPG_MENU_SOURCE\033[36m$UPG_MENU_SOURCE_NAME\033[0m" \
+ "8) \033[31m$UPG_MENU_UNINSTALL\033[0m" \
+ "9) \033[36m$UPG_MENU_THANKS\033[0m" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
case "$num" in
- ""|0)
+ "" | 0)
break
;;
1)
@@ -65,330 +62,445 @@ upgrade() {
setcrt
;;
6)
- echo "-----------------------------------------------"
- echo -e "PAC配置链接为:\033[30;47m http://$host:$db_port/ui/pac \033[0m"
- echo -e "PAC的使用教程请参考:\033[4;32mhttps://juewuy.github.io/ehRUeewcv\033[0m"
- sleep 2
+ msg_alert -t 2 "$UPG_PAC_LINK\033[30;47m http://$host:$db_port/ui/pac \033[0m" \
+ "$UPG_PAC_GUIDE\033[4;32mhttps://juewuy.github.io/ehRUeewcv\033[0m"
;;
7)
setserver
;;
8)
- . "$CRASHDIR"/menus/5_task.sh && task_add
- ;;
- 9)
. "$CRASHDIR"/menus/uninstall.sh && uninstall
;;
- 99)
- echo "-----------------------------------------------"
- echo -e "感谢:\033[32mClash项目 \033[0m作者\033[36m Dreamacro\033[0m"
- echo -e "感谢:\033[32msing-box项目 \033[0m作者\033[36m SagerNet\033[0m 项目地址:\033[32mhttps://github.com/SagerNet/sing-box\033[0m"
- echo -e "感谢:\033[32mMetaCubeX项目 \033[0m作者\033[36m MetaCubeX\033[0m 项目地址:\033[32mhttps://github.com/MetaCubeX\033[0m"
- echo -e "感谢:\033[32mYACD面板项目 \033[0m作者\033[36m haishanh\033[0m 项目地址:\033[32mhttps://github.com/haishanh/yacd\033[0m"
- echo -e "感谢:\033[32mzashboard项目 \033[0m作者\033[36m Zephyruso\033[0m 项目地址:\033[32mhttps://github.com/Zephyruso/zashboard\033[0m"
- echo -e "感谢:\033[32mSubconverter \033[0m作者\033[36m tindy2013\033[0m 项目地址:\033[32mhttps://github.com/tindy2013/subconverter\033[0m"
- echo -e "感谢:\033[32msing-box分支项目 \033[0m作者\033[36m PuerNya\033[0m 项目地址:\033[32mhttps://github.com/PuerNya/sing-box\033[0m"
- echo -e "感谢:\033[32msing-box分支项目 \033[0m作者\033[36m reF1nd\033[0m 项目地址:\033[32mhttps://github.com/reF1nd/sing-box\033[0m"
- echo -e "感谢:\033[32mDustinWin相关项目 \033[0m作者\033[36m DustinWin\033[0m 作者地址:\033[32mhttps://github.com/DustinWin\033[0m"
- echo "-----------------------------------------------"
- echo -e "特别感谢:\033[36m所有帮助及赞助过此项目的同仁们!\033[0m"
- echo "-----------------------------------------------"
+ 9)
+ comp_box "$UPG_THANKS_TITLE"
+ btm_box "\033[32m$UPG_THANKS_ITEM_CLASH\033[0m" \
+ "" \
+ "\033[32m$UPG_THANKS_ITEM_SINGBOX\033[0m" \
+ "$UPG_THANKS_ITEM_SINGBOX_URL" \
+ "" \
+ "\033[32m$UPG_THANKS_ITEM_METACUBE\033[0m" \
+ "$UPG_THANKS_ITEM_METACUBE_URL" \
+ "" \
+ "\033[32m$UPG_THANKS_ITEM_YACD\033[0m" \
+ "$UPG_THANKS_ITEM_YACD_URL" \
+ "" \
+ "\033[32m$UPG_THANKS_ITEM_ZASH\033[0m" \
+ "$UPG_THANKS_ITEM_ZASH_URL" \
+ "" \
+ "\033[32m$UPG_THANKS_ITEM_SUB\033[0m" \
+ "$UPG_THANKS_ITEM_SUB_URL" \
+ "" \
+ "\033[32m$UPG_THANKS_ITEM_REF1ND\033[0m" \
+ "$UPG_THANKS_ITEM_REF1ND_URL" \
+ "" \
+ "\033[32m$UPG_THANKS_ITEM_DUSTIN\033[0m" \
+ "$UPG_THANKS_ITEM_DUSTIN_URL" \
+ ""
+ btm_box "$UPG_THANKS_SPECIAL"
sleep 2
;;
*)
errornum
- sleep 1
- break
;;
esac
done
}
-#检查更新
-checkupdate(){
- echo -ne "\033[32m正在检查更新!\033[0m\r"
- get_bin "$TMPDIR"/version_new version echooff
- [ "$?" = "0" ] && {
- version_new=$(cat "$TMPDIR"/version_new)
- get_bin "$TMPDIR"/version_new bin/version echooff
- }
- if [ "$?" = "0" ];then
- . "$TMPDIR"/version_new 2>/dev/null
- else
- echo -e "\033[31m检查更新失败!请尝试切换其他安装源!\033[0m"
- setserver
- [ "$checkupdate" = false ] || checkupdate
- fi
- rm -rf "$TMPDIR"/version_new
+# 检查更新
+checkupdate() {
+ line_break
+ separator_line "="
+ content_line "\033[32m$UPG_CHECKING\033[0m"
+ get_bin "$TMPDIR"/version_new version echooff
+ [ "$?" = "0" ] && {
+ version_new=$(cat "$TMPDIR"/version_new)
+ get_bin "$TMPDIR"/version_new bin/version echooff
+ content_line "\033[32m$UPG_CHECK_OK\033[0m"
+ separator_line "="
+ }
+ if [ "$?" = "0" ]; then
+ . "$TMPDIR"/version_new 2>/dev/null
+ else
+ content_line "\033[31m$UPG_CHECK_FAIL\033[0m"
+ separator_line "="
+ setserver
+ if [ "$checkupdate" != false ]; then
+ checkupdate
+ fi
+ fi
+ rm -rf "$TMPDIR"/version_new
}
-#更新脚本
-getscripts(){
- get_bin "$TMPDIR"/ShellCrash.tar.gz ShellCrash.tar.gz
- if [ "$?" != "0" ];then
- echo -e "\033[33m文件下载失败!\033[0m"
- error_down
- else
- "$CRASHDIR"/start.sh stop 2>/dev/null
- #解压
- echo "-----------------------------------------------"
- echo "开始解压文件!"
- mkdir -p "$CRASHDIR" > /dev/null
- tar -zxf "$TMPDIR/ShellCrash.tar.gz" ${tar_para} -C "$CRASHDIR"/
- if [ $? -ne 0 ];then
- echo -e "\033[33m文件解压失败!\033[0m"
- error_down
- else
- . "$CRASHDIR"/init.sh >/dev/null
- echo "$release_type" | grep -qE '^[0-9]' && setconfig userguide #回退时重新新手引导
- echo -e "\033[32m脚本更新成功!\033[0m"
- fi
- fi
- rm -rf "$TMPDIR"/ShellCrash.tar.gz
- exit
-}
-setscripts(){
- echo "-----------------------------------------------"
- echo -e "当前脚本版本为:\033[33m $versionsh_l \033[0m"
- echo -e "最新脚本版本为:\033[32m $version_new \033[0m"
- echo -e "注意更新时会停止服务!"
- echo "-----------------------------------------------"
- read -p "是否更新脚本?[1/0] > " res
- if [ "$res" = '1' ]; then
- #下载更新
- getscripts
- #提示
- echo "-----------------------------------------------"
- echo -e "\033[32m管理脚本更新成功!\033[0m"
- echo "-----------------------------------------------"
- exit;
- fi
+# 更新脚本
+getscripts() {
+ line_break
+ separator_line "="
+ get_bin "$TMPDIR"/ShellCrash.tar.gz ShellCrash.tar.gz
+
+ if [ "$?" != "0" ]; then
+ content_line "\033[33m$UPG_DOWNLOAD_FAIL\033[0m"
+ error_down
+ else
+ "$CRASHDIR"/start.sh stop 2>/dev/null
+ # 解压
+ content_line "$UPG_EXTRACTING"
+ mkdir -p "$CRASHDIR" >/dev/null
+ tar -zxf "$TMPDIR/ShellCrash.tar.gz" ${tar_para} -C "$CRASHDIR"/
+ if [ $? -ne 0 ]; then
+ content_line "\033[33m$UPG_EXTRACT_FAIL\033[0m"
+ error_down
+ else
+ . "$CRASHDIR"/init.sh >/dev/null
+ echo "$release_type" | grep -qE '^[0-9]' && setconfig userguide #回退时重新新手引导
+ content_line "\033[32m$UPG_SCRIPT_OK\033[0m"
+ separator_line "="
+ fi
+ fi
+ rm -rf "$TMPDIR"/ShellCrash.tar.gz
+ exit
}
-#更新内核
-setcpucore(){ #手动设置内核架构
- cpucore_list="armv5 armv7 arm64 386 amd64 mipsle-softfloat mipsle-hardfloat mips-softfloat"
- echo "-----------------------------------------------"
- echo -e "\033[31m仅适合脚本无法正确识别核心或核心无法正常运行时使用!\033[0m"
- echo -e "当前可供在线下载的处理器架构为:"
- echo $cpucore_list | awk -F " " '{for(i=1;i<=NF;i++) {print i" "$i }}'
- echo -e "不知道如何获取核心版本?请参考:\033[36;4mhttps://juewuy.github.io/bdaz\033[0m"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- [ -n "$num" ] && setcpucore=$(echo $cpucore_list | awk '{print $"'"$num"'"}' )
- if [ -z "$setcpucore" ];then
- echo -e "\033[31m请输入正确的处理器架构!\033[0m"
- sleep 1
- cpucore=""
- else
- cpucore=$setcpucore
- setconfig cpucore $cpucore
- fi
+setscripts() {
+ while true; do
+ comp_box "\033[33m$UPG_SCRIPT_WARN\033[0m" \
+ "" \
+ "$UPG_SCRIPT_CUR_VER\033[36m$versionsh_l\033[0m" \
+ "$UPG_SCRIPT_NEW_VER\033[32m$version_new\033[0m"
+ btm_box "1) $UPG_UPDATE_NOW" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " res
+ case "$res" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ # 下载更新
+ getscripts
+ # 提示
+ msg_alert "\033[32m$UPG_SCRIPT_MGR_OK\033[0m"
+ line_break
+ exit 0
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
}
-setcoretype(){ #手动指定内核类型
- echo "$crashcore" | grep -q 'singbox' && core_old=singbox || core_old=clash
- echo -e "\033[33m请确认该自定义内核的类型:\033[0m"
- echo -e " 1 Clash基础内核"
- echo -e " 2 Clash-Premium内核"
- echo -e " 3 Mihomo(Meta)内核"
- echo -e " 4 Sing-Box内核"
- echo -e " 5 Sing-Box-reF1nd内核"
- read -p "请输入对应数字 > " num
- case "$num" in
- 2) crashcore=clashpre ;;
- 3) crashcore=meta ;;
- 4) crashcore=singbox ;;
- 5) crashcore=singboxr ;;
- *) crashcore=clash ;;
- esac
- echo "$crashcore" | grep -q 'singbox' && core_new=singbox || core_new=clash
+
+# 更新内核
+# 手动设置内核架构
+setcpucore() {
+ cpucore_list="armv5 armv7 arm64 386 amd64 mipsle-softfloat mipsle-hardfloat mips-softfloat"
+
+ comp_box "\033[31m$UPG_CPUCORE_HINT1\033[0m" \
+ "$UPG_CPUCORE_HINT2" \
+ "$UPG_CPUCORE_HINT3\033[36;4mhttps://juewuy.github.io/bdaz\033[0m"
+ content_line "$UPG_CPUCORE_LIST"
+ separator_line "-"
+
+ echo "$cpucore_list" |
+ awk '{for(i=1;i<=NF;i++) print i") "$i}' |
+ while IFS= read -r line; do
+ content_line "$line"
+ done
+
+ separator_line "="
+ read -r -p "$COMMON_INPUT> " num
+ [ -n "$num" ] && setcpucore=$(echo "$cpucore_list" | awk '{print $"'"$num"'"}')
+ if [ -z "$setcpucore" ]; then
+ cpucore=""
+ msg_alert "\033[31m$UPG_CPUCORE_ERR\033[0m"
+ else
+ cpucore=$setcpucore
+ setconfig cpucore "$cpucore"
+ fi
}
-switch_core(){ #clash与singbox内核切换
- #singbox和clash内核切换时提示是否保留文件
- [ "$core_new" != "$core_old" ] && {
- [ "$dns_mod" = "redir_host" ] && [ "$core_old" = "clash" ] && setconfig dns_mod mix #singbox自动切换dns
- [ "$dns_mod" = "mix" ] && [ "$crashcore" = 'clash' -o "$crashcore" = 'clashpre' ] && setconfig dns_mod redir_host #singbox自动切换dns
- echo -e "\033[33m已从$core_old内核切换至$core_new内核\033[0m"
- echo -e "\033[33m二者Geo数据库及yaml/json配置文件不通用\033[0m"
- read -p "是否保留相关数据库文件?(1/0) > " res
- [ "$res" = '0' ] && {
- [ "$core_old" = "clash" ] && {
- geodate='Country.mmdb GeoSite.dat ruleset/*.mrs ruleset/*.yaml ruleset/*.yml'
- geodate_v='Country_v cn_mini_v geosite_v mrs_geosite_cn_v'
- }
- [ "$core_old" = "singbox" ] && {
- geodate='geoip.db geosite.db ruleset/*.srs ruleset/*.json'
- geodate_v='geoip_cn_v geosite_cn_v srs_geoip_cn_v srs_geosite_cn_v'
- }
- for text in ${geodate} ;do
- rm -rf "$CRASHDIR"/${text}
- done
- for text in ${geodate_v} ;do
- setconfig "$text"
- done
- }
- }
+
+# 手动指定内核类型
+setcoretype() {
+ while true; do
+ echo "$crashcore" | grep -q 'singbox' && core_old=singbox || core_old=clash
+ comp_box "\033[33m$UPG_CORETYPE_CONFIRM\033[0m"
+ btm_box "1) Mihomo(Meta)" \
+ "2) Singbox-reF1nd" \
+ "3) Singbox" \
+ "4) Clash" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 0) ;;
+ 1)
+ crashcore=meta
+ ;;
+ 2)
+ crashcore=singboxr
+ ;;
+ 3)
+ crashcore=singbox
+ ;;
+ 4)
+ crashcore=clash
+ ;;
+ *)
+ errornum
+ continue
+ ;;
+ esac
+ echo "$crashcore" | grep -q 'singbox' && core_new=singbox || core_new=clash
+ break
+ done
}
-getcore(){ #下载内核文件
- . "$CRASHDIR"/libs/core_tools.sh #调用下载工具
- [ -z "$crashcore" ] && crashcore=meta
- [ -z "$cpucore" ] && check_cpucore
- [ "$crashcore" = unknow ] && setcoretype
- echo "$crashcore" | grep -q 'singbox' && core_new=singbox || core_new=clash
- #获取在线内核文件
- echo "-----------------------------------------------"
- echo "正在在线获取$crashcore核心文件……"
- core_webget
- case "$?" in
- 0)
- echo -e "\033[32m$crashcore核心下载成功!\033[0m"
- sleep 1
- switch_core
- ;;
- 1)
- echo -e "\033[31m核心文件下载失败!\033[0m"
- [ -z "$custcorelink" ] && error_down
- ;;
- *)
- echo -e "\033[31m核心文件下载成功但校验失败!请尝试手动指定CPU版本\033[0m"
- rm -rf ${TMPDIR}/core_new
- rm -rf ${TMPDIR}/core_new.tar.gz
- setcpucore
- ;;
- esac
+
+# clash与singbox内核切换
+switch_core() {
+ # singbox和clash内核切换时提示是否保留文件
+ [ "$core_new" != "$core_old" ] && {
+ [ "$dns_mod" = "redir_host" ] && [ "$core_old" = "clash" ] && setconfig dns_mod mix #singbox自动切换dns
+ [ "$dns_mod" = "mix" ] && [ "$crashcore" = 'clash' -o "$crashcore" = 'clashpre' ] && setconfig dns_mod redir_host #singbox自动切换dns
+ comp_box "\033[33m$UPG_CORE_SWITCH_PREFIX$core_old$UPG_CORE_SWITCH_MID$core_new$UPG_CORE_SWITCH_SUFFIX\033[0m" \
+ "\033[33m$UPG_CORE_SWITCH_WARN\033[0m" \
+ "$UPG_CORE_SWITCH_KEEP"
+ btm_box "1) $UPG_KEEP" \
+ "0) $UPG_NOT_KEEP"
+ read -r -p "$COMMON_INPUT> " res
+ [ "$res" = '0' ] && {
+ [ "$core_old" = "clash" ] && {
+ geodate='Country.mmdb GeoSite.dat ruleset/*.mrs ruleset/*.yaml ruleset/*.yml'
+ geodate_v='Country_v cn_mini_v geosite_v mrs_geosite_cn_v'
+ }
+ [ "$core_old" = "singbox" ] && {
+ geodate='geoip.db geosite.db ruleset/*.srs ruleset/*.json'
+ geodate_v='geoip_cn_v geosite_cn_v srs_geoip_cn_v srs_geosite_cn_v'
+ }
+ for text in ${geodate}; do
+ rm -rf "$CRASHDIR"/${text}
+ done
+ for text in ${geodate_v}; do
+ setconfig "$text"
+ done
+ }
+ }
}
-setcustcore(){ #自定义内核
- checkcustcore(){
- [ "$api_tag" = "latest" ] && api_url=latest || api_url="tags/$api_tag"
- #通过githubapi获取内核信息
- echo -e "\033[32m正在获取内核文件链接!\033[0m"
- webget "$TMPDIR"/github_api https://api.github.com/repos/${project}/releases/${api_url}
- if [ "$?" = 0 ];then
- release_tag=$(cat "$TMPDIR"/github_api | grep '"tag_name":' | awk -F '"' '{print $4}')
- release_date=$(cat "$TMPDIR"/github_api | grep '"published_at":' | awk -F '"' '{print $4}')
- update_date=$(cat "$TMPDIR"/github_api | grep '"updated_at":' | head -n 1 | awk -F '"' '{print $4}')
- [ -n "$(echo $cpucore | grep mips)" ] && cpu_type=mips || cpu_type=$cpucore
- cat "$TMPDIR"/github_api | grep "browser_download_url" | grep -oE "https://github.com/${project}/releases/download.*linux.*${cpu_type}.*\.gz\"$" | sed 's/"//' > "$TMPDIR"/core.list
- rm -rf "$TMPDIR"/github_api
- #
- if [ -s "$TMPDIR"/core.list ];then
- echo "-----------------------------------------------"
- echo -e "内核版本:\033[36m$release_tag\033[0m"
- echo -e "发布时间:\033[33m$release_date\033[0m"
- echo -e "更新时间:\033[32m$update_date\033[0m"
- echo "-----------------------------------------------"
- echo -e "\033[33m请确认内核信息并选择:\033[0m"
- cat "$TMPDIR"/core.list | grep -oE "$release_tag.*" | sed 's|.*/||' | awk '{print " "NR" "$1}'
- echo -e " 0 返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0)
- setcustcore
- ;;
- [1-9]|[1-9][0-9])
- if [ "$num" -le "$(wc -l < "$TMPDIR"/core.list)" ];then
- custcorelink=$(sed -n "$num"p "$TMPDIR"/core.list)
- getcore
- else
- errornum
- fi
- ;;
- *)
- errornum
- ;;
- esac
- else
- echo -e "\033[31m找不到可用内核,可能是作者没有编译相关CPU架构版本的内核文件!\033[0m"
- sleep 1
- fi
- else
- echo -e "\033[31m查找失败,请尽量在服务启动后再使用本功能!\033[0m"
- sleep 1
- fi
- rm -rf "$TMPDIR"/core.list
- }
- [ -z "$cpucore" ] && check_cpucore
- echo "-----------------------------------------------"
- echo -e "\033[36m此处内核通常源自互联网采集,此处致谢各位开发者!\033[0m"
- echo -e "\033[33m自定义内核未经过完整适配,使用出现问题请自行解决!\033[0m"
- echo -e "\033[31m自定义内核已适配定时任务,但不支持小闪存模式!\033[0m"
- echo -e "\033[32m如遇到网络错误请先启动ShellCrash服务!\033[0m"
- [ -n "$custcore" ] && {
- echo "-----------------------------------------------"
- echo -e "当前内核为:\033[36m$custcore\033[0m"
- }
- echo "-----------------------------------------------"
- echo -e "\033[33m请选择需要使用的核心!\033[0m"
- echo -e "1 \033[36mMetaCubeX/mihomo\033[32m@release\033[0m版本官方内核"
- echo -e "2 \033[36mvernesong/mihomo\033[32m@alpha\033[0m版本内核(支持Smart策略)"
- echo -e "3 \033[36mSagerNet/sing-box\033[32m@release\033[0m版本官方内核"
- echo -e "4 Premium-2023.08.17内核(已停止维护)"
- echo -e "9 \033[33m自定义内核链接 \033[0m"
- echo "-----------------------------------------------"
- echo -e " 0 返回上级菜单"
- read -p "请输入对应数字 > " num
- case "$num" in
- 1)
- project=MetaCubeX/mihomo
- api_tag=latest
- crashcore=meta
- checkcustcore
- ;;
- 2)
- project=vernesong/mihomo
- api_tag=Prerelease-Alpha
- crashcore=meta
- checkcustcore
- ;;
- 3)
- project=SagerNet/sing-box
- api_tag=latest
- crashcore=singbox
- checkcustcore
- ;;
- 4)
- project=juewuy/ShellCrash
- api_tag=clash.premium.latest
- crashcore=clashpre
- checkcustcore
- ;;
- 9)
- read -p "请输入自定义内核的链接地址(必须是以.tar.gz、.upx或.gz结尾的压缩文件) > " link
- [ -n "$link" ] && custcorelink="$link"
- setcoretype
- getcore
- ;;
- *)
- ;;
- esac
+
+# 下载内核文件
+getcore() {
+ # 调用下载工具
+ . "$CRASHDIR"/libs/core_tools.sh
+
+ [ -z "$crashcore" ] && crashcore=meta
+ [ -z "$cpucore" ] && check_cpucore
+ [ "$crashcore" = unknow ] && setcoretype
+ if echo "$crashcore" | grep -q 'singbox'; then
+ core_new=singbox
+ else
+ core_new=clash
+ fi
+ # 获取在线内核文件
+ line_break
+ separator_line "="
+ content_line "${UPG_GETTING_CORE_TEXT_PREFIX}${crashcore}${UPG_GETTING_CORE_TEXT_SUFFIX}"
+ core_webget
+ case "$?" in
+ 0)
+ content_line "\033[32m${UPG_CORE_DOWNLOAD_OK_TEXT_PREFIX}${crashcore}${UPG_CORE_DOWNLOAD_OK_TEXT_SUFFIX}\033[0m"
+ separator_line "="
+ sleep 1
+ switch_core
+ ;;
+ 1)
+ content_line "\033[31m$UPG_CORE_DOWNLOAD_FAIL_TEXT\033[0m"
+ separator_line "="
+ [ -z "$custcorelink" ] && error_down
+ ;;
+ *)
+ content_line "\033[31m$UPG_CORE_DOWNLOAD_VERIFY_FAIL_TEXT\033[0m"
+ content_line "\033[31m$UPG_CORE_DOWNLOAD_VERIFY_HINT_TEXT\033[0m"
+ separator_line "="
+ sleep 1
+ rm -rf "${TMPDIR}"/core_new
+ rm -rf "${TMPDIR}"/core_new.tar.gz
+ setcpucore
+ ;;
+ esac
}
-setziptype(){
- echo "-----------------------------------------------"
- echo -e "请选择内核内核分支及压缩方式:\033[0m"
- echo "-----------------------------------------------"
- echo -e " 1 \033[36m最简编译release版本,upx压缩\033[0m-不支持Gvisor,Tailscale,Wireguard,NaiveProxy"
- echo -e " 2 \033[32m标准编译release版本,tar.gz压缩\033[0m-完整支持脚本全部内置功能"
- echo -e " 3 \033[33m完整编译alpha版本,gz压缩\033[0m-占用可能略高,稳定性自测"
- echo "-----------------------------------------------"
- echo " 0 返回上级菜单"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0) ;;
- 1)
- zip_type='upx'
- ;;
- 2)
- zip_type='tar.gz'
- ;;
- 3)
- zip_type='gz'
- ;;
- *)
- errornum
- ;;
- esac
- setconfig zip_type "$zip_type"
+
+checkcustcore() {
+ [ "$api_tag" = "latest" ] && api_url=latest || api_url="tags/$api_tag"
+ # 通过githubapi获取内核信息
+ line_break
+ separator_line "="
+ content_line "\033[32m$UPG_CORE_GET_LINK_TITLE\033[0m"
+ webget "$TMPDIR"/github_api https://api.github.com/repos/"${project}"/releases/"${api_url}"
+ if [ "$?" = 0 ]; then
+ release_tag=$(cat "$TMPDIR"/github_api | grep '"tag_name":' | awk -F '"' '{print $4}')
+ release_date=$(cat "$TMPDIR"/github_api | grep '"published_at":' | awk -F '"' '{print $4}')
+ update_date=$(cat "$TMPDIR"/github_api | grep '"updated_at":' | head -n 1 | awk -F '"' '{print $4}')
+ echo "$cpucore" | grep -q 'mips' && cpu_type=mips || cpu_type=$cpucore
+ cat "$TMPDIR"/github_api | grep "browser_download_url" | grep -oE "https://github.com/${project}/releases/download.*linux.*${cpu_type}.*\.(gz|upx)\"$" | sed 's/"//' >"$TMPDIR"/core.list
+ rm -rf "$TMPDIR"/github_api
+
+ if [ -s "$TMPDIR"/core.list ]; then
+ separator_line "="
+
+ comp_box "$UPG_CORE_INFO_TITLE\033[36m$release_tag\033[0m" \
+ "$UPG_CORE_INFO_TIME1\033[33m$release_date\033[0m" \
+ "$UPG_CORE_INFO_TIME2\033[32m$update_date\033[0m"
+ content_line "\033[33m$UPG_CORE_INFO_SELECT\033[0m"
+ separator_line "-"
+ grep -oE "$release_tag.*" "$TMPDIR/core.list" |
+ sed 's|.*/||' |
+ awk '{print NR") "$1}' |
+ while IFS= read -r line; do
+ content_line "$line"
+ done
+ btm_box "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ 0)
+ return 0
+ ;;
+ [1-9] | [1-9][0-9])
+ if [ "$num" -le "$(wc -l <"$TMPDIR"/core.list)" ]; then
+ custcorelink=$(sed -n "$num"p "$TMPDIR"/core.list)
+ getcore
+ else
+ errornum
+ fi
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ else
+ content_line "\033[31m$UPG_CORE_NOT_FOUND\033[0m"
+ separator_line "="
+ sleep 1
+ fi
+ else
+ content_line "\033[31m$UPG_CORE_CHECK_FAIL_HINT\033[0m"
+ separator_line "="
+ sleep 1
+ fi
+ rm -rf "$TMPDIR"/core.list
+}
+
+# 自定义内核
+setcustcore() {
+ while true; do
+ [ -z "$cpucore" ] && check_cpucore
+ [ -n "$custcorelink" ] && custcore="$(echo "$custcorelink" | sed 's#.*github.com##; s#/releases/download/#@#')"
+ line_break
+ separator_line "="
+ content_line "\033[36m$UPG_CUSTOM_CORE_SOURCE\033[0m"
+ content_line "\033[33m$UPG_CUSTOM_CORE_WARN\033[0m"
+ content_line "\033[31m$UPG_CUSTOM_CORE_TASK_WARN\033[0m"
+ content_line "\033[32m$UPG_CUSTOM_CORE_NET_WARN\033[0m"
+ [ -n "$custcore" ] && {
+ content_line "$UPG_CUSTOM_CORE_CURRENT\033[36m$custcore\033[0m"
+ }
+ separator_line "="
+ content_line "$UPG_CUSTOM_CORE_SELECT"
+ separator_line "-"
+ btm_box "1) \033[36mMetaCubeX/mihomo\033[32m@release\033[0m$UPG_CUSTOM_CORE_MENU_OFFICIAL" \
+ "2) \033[36mvernesong/mihomo\033[32m@alpha\033[0m$UPG_CUSTOM_CORE_MENU_ALPHA" \
+ "3) \033[36mSagerNet/sing-box\033[32m@release\033[0m$UPG_CUSTOM_CORE_MENU_OFFICIAL" \
+ "4) \033[36mDustinWin/mihomo\033[0m$UPG_CUSTOM_CORE_MENU_MULTI" \
+ "5) \033[36mDustinWin/sing-boxr\033[0m$UPG_CUSTOM_CORE_MENU_MULTI" \
+ "9) $UPG_CUSTOM_CORE_LINK_MENU" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ project=MetaCubeX/mihomo
+ api_tag=latest
+ crashcore=meta
+ checkcustcore
+ ;;
+ 2)
+ project=vernesong/mihomo
+ api_tag=Prerelease-Alpha
+ crashcore=meta
+ checkcustcore
+ ;;
+ 3)
+ project=SagerNet/sing-box
+ api_tag=latest
+ crashcore=singbox
+ checkcustcore
+ ;;
+ 4)
+ project=DustinWin/proxy-tools
+ api_tag=mihomo
+ crashcore=meta
+ checkcustcore
+ ;;
+ 5)
+ project=DustinWin/proxy-tools
+ api_tag=sing-box
+ crashcore=singboxr
+ checkcustcore
+ ;;
+ 6)
+ project=vernesong/mihomo-oix
+ api_tag=Pre-Alpha
+ crashcore=meta
+ checkcustcore
+ ;;
+ 9)
+ comp_box "$UPG_CUSTOM_CORE_LINK_HINT" \
+ "$UPG_CUSTOM_CORE_LINK_HINT2" \
+ "" \
+ "$UPG_CUSTOM_CORE_LINK_HINT3"
+ read -r -p "$UPG_SOURCE_CUSTOM_INPUT" link
+ if [ "$link" = 0 ]; then
+ continue
+ elif [ -n "$link" ]; then
+ custcorelink="$link"
+ setcoretype
+ getcore
+ fi
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
+}
+
+setziptype() {
+ comp_box "\033[0m$UPG_ZIPTYPE_TITLE"
+ content_line "$UPG_ZIPTYPE_1"
+ sub_content_line "$UPG_CUSTOM_CORE_NOTE1"
+ content_line "$UPG_ZIPTYPE_2"
+ sub_content_line "$UPG_ZIPTYPE_2_HINT"
+ content_line "$UPG_ZIPTYPE_3"
+ sub_content_line "$UPG_ZIPTYPE_3_HINT"
+ content_line "0) $COMMON_BACK"
+ separator_line "="
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 0) ;;
+ 1)
+ zip_type='upx'
+ ;;
+ 2)
+ zip_type='tar.gz'
+ ;;
+ 3)
+ zip_type='gz'
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ setconfig zip_type "$zip_type"
}
# 内核选择菜单
@@ -398,48 +510,43 @@ setcore() {
[ -z "$crashcore" ] && crashcore="unknow"
[ -z "$zip_type" ] && zip_type="tar.gz"
echo "$crashcore" | grep -q 'singbox' && core_old=singbox || core_old=clash
- [ -n "$custcorelink" ] && custcore="$(echo $custcorelink | sed 's#.*github.com##; s#/releases/download/#@#')"
- ###
- echo "-----------------------------------------------"
+
[ -z "$cpucore" ] && check_cpucore
- echo -e "当前内核:\033[42;30m $crashcore \033[47;30m$core_v\033[0m"
- echo -e "当前系统处理器架构:\033[32m $cpucore \033[0m"
- echo -e "\033[33m请选择需要使用的核心版本!\033[0m"
- echo -e "\033[36m如需本地上传,请将.upx .gz .tar.gz文件上传至 /tmp 目录后重新运行crash命令\033[0m"
- echo "-----------------------------------------------"
- echo -e "1 \033[43;30m Mihomo \033[0m: \033[32m(原meta内核)支持全面\033[0m"
- echo -e " >>\033[32m$meta_v \033[33m占用略高\033[0m"
- echo -e " 说明文档: \033[36;4mhttps://wiki.metacubex.one\033[0m"
- echo -e "2 \033[43;30m SingBoxR \033[0m: \033[32m支持全面\033[0m"
- echo -e " >>\033[32m$singboxr_v \033[33m使用reF1nd增强分支\033[0m"
- echo -e " 说明文档: \033[36;4mhttps://sing-boxr.dustinwin.us.kg\033[0m"
+
+ comp_box "$UPG_CORE_MENU_CURRENT\033[42;30m$crashcore\033[47;30m $core_v\033[0m" \
+ "$UPG_CORE_MENU_SYS\033[32m$cpucore\033[0m" \
+ "\033[36m$UPG_CORE_MENU_LOCAL_HINT\033[0m" \
+ "" \
+ "\033[33m$UPG_CORE_MENU_SELECT\033[0m"
+
+ content_line "${UPG_CORE_V1_PREFIX}${meta_v}${UPG_CORE_V1_SUFFIX}"
+ sub_content_line "$UPG_CORE_V1_DOC"
+
+ content_line "${UPG_CORE_V2_PREFIX}${singboxr_v}${UPG_CORE_V2_SUFFIX}"
+ sub_content_line "$UPG_CORE_V2_DOC"
+
[ "$zip_type" = 'upx' ] && {
- echo -e "3 \033[43;30m SingBox \033[0m: \033[32m占用较低\033[0m"
- echo -e " >>\033[32m$singbox_v \033[33m不支持providers\033[0m"
- echo -e " 说明文档: \033[36;4mhttps://sing-box.sagernet.org\033[0m"
+ content_line "${UPG_CORE_V3_PREFIX}${singbox_v}${UPG_CORE_V3_SUFFIX}"
+ sub_content_line "$UPG_CORE_V3_DOC"
}
[ "$zip_type" = 'upx' ] && {
- echo -e "4 \033[43;30m Clash \033[0m: \033[32m占用低\033[0m"
- echo -e " >>\033[32m$clash_v \033[33m不安全,已停止维护\033[0m"
- echo -e " 说明文档: \033[36;4mhttps://lancellc.gitbook.io\033[0m"
+ content_line "${UPG_CORE_V4_PREFIX}${clash_v}${UPG_CORE_V4_SUFFIX}"
+ sub_content_line "$UPG_CORE_V4_DOC"
}
- echo "-----------------------------------------------"
- echo -e "5 切换版本分支及压缩方式: \033[32m$zip_type\033[0m"
- echo -e "6 \033[36m使用自定义内核\033[0m $custcore"
- echo -e "7 \033[32m更新当前内核\033[0m"
- echo "-----------------------------------------------"
- echo "9 手动指定处理器架构"
- echo "-----------------------------------------------"
- echo "0 返回上级菜单"
- read -p "请输入对应数字 > " num
+ btm_box "${UPG_CORE_MENU_5_PREFIX}${zip_type}${UPG_CORE_MENU_5_SUFFIX}" \
+ "${UPG_CORE_MENU_6_PREFIX}${UPG_CORE_MENU_6_SUFFIX}" \
+ "$UPG_CORE_MENU_7" \
+ "$UPG_CORE_MENU_9" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
case "$num" in
"" | 0)
break
;;
1)
[ -d "/jffs" ] && {
- echo -e "\033[31mMeta内核使用的GeoSite.dat数据库在华硕设备存在被系统误删的问题,可能无法使用!\033[0m"
- sleep 3
+ msg_alert -t 2 "\033[31m$UPG_CORE_ASUS_WARN\033[0m"
}
crashcore=meta
custcorelink=''
@@ -480,80 +587,88 @@ setcore() {
;;
*)
errornum
- sleep 1
- break
;;
esac
done
}
-#数据库
-getgeo(){ #下载Geo文件
- #生成链接
- echo "-----------------------------------------------"
- echo "正在从服务器获取数据库文件…………"
- get_bin "$TMPDIR"/${geoname} bin/geodata/$geotype
- if [ "$?" = "1" ];then
- echo "-----------------------------------------------"
- echo -e "\033[31m文件下载失败!\033[0m"
- error_down
- else
- echo "$geoname" | grep -Eq '.mrs|.srs|.tar.gz' && {
- geofile='ruleset/'
- [ ! -d "$BINDIR"/ruleset ] && mkdir -p "$BINDIR"/ruleset
- }
- if echo "$geoname" | grep -Eq '.tar.gz';then
- tar -zxf "$TMPDIR"/${geoname} ${tar_para} -C "$BINDIR"/${geofile} > /dev/null
- [ $? -ne 0 ] && echo "文件解压失败!" && rm -rf "$TMPDIR"/${geoname} && exit 1
- rm -rf "$TMPDIR"/${geoname}
- else
- mv -f "$TMPDIR"/${geoname} "$BINDIR"/${geofile}${geoname}
- fi
- echo "-----------------------------------------------"
- echo -e "\033[32m$geotype数据库文件下载成功!\033[0m"
- geo_v="$(echo $geotype | awk -F "." '{print $1}')_v"
- setconfig $geo_v $GeoIP_v
- fi
- sleep 1
+# 数据库
+# 下载Geo文件
+getgeo() {
+ # 生成链接
+ line_break
+ separator_line "="
+ content_line "$UPG_GEO_GETTING"
+ get_bin "$TMPDIR"/"${geoname}" bin/geodata/"$geotype"
+ if [ "$?" = "1" ]; then
+ content_line "\033[31m$UPG_DOWNLOAD_FAIL\033[0m"
+ error_down
+ else
+ echo "$geoname" | grep -Eq '.mrs|.srs|.tar.gz' && {
+ geofile='ruleset/'
+ [ ! -d "$BINDIR"/ruleset ] && mkdir -p "$BINDIR"/ruleset
+ }
+ if echo "$geoname" | grep -Eq '.tar.gz'; then
+ tar -zxf "$TMPDIR"/"${geoname}" ${tar_para} -C "$BINDIR"/"${geofile}" >/dev/null
+ if [ $? -ne 0 ]; then
+ content_line "$UPG_EXTRACT_FAIL"
+ separator_line "="
+ sleep 1
+ line_break
+ rm -rf "$TMPDIR"/${geoname}
+ exit 1
+ fi
+ rm -rf "$TMPDIR"/${geoname}
+ else
+ mv -f "$TMPDIR"/"${geoname}" "$BINDIR"/"${geofile}""${geoname}"
+ fi
+ content_line "\033[32m${UPG_GEO_OK_PREFIX}${geotype}${UPG_GEO_OK_SUFFIX}\033[0m"
+ geo_v="$(echo "$geotype" | awk -F "." '{print $1}')_v"
+ setconfig "$geo_v" "$GeoIP_v"
+ fi
+ sleep 1
}
-getcustgeo(){
- echo "-----------------------------------------------"
- echo "正在获取数据库文件…………"
- webget "$TMPDIR"/$geoname $custgeolink
- if [ "$?" = "1" ];then
- echo "-----------------------------------------------"
- echo -e "\033[31m文件下载失败!\033[0m"
- error_down
- else
- echo "$geoname" | grep -Eq '.mrs|.srs' && {
- geofile='ruleset/'
- [ ! -d "$BINDIR"/ruleset ] && mkdir -p "$BINDIR"/ruleset
- }
- mv -f "$TMPDIR"/${geoname} "$BINDIR"/${geofile}${geoname}
- echo "-----------------------------------------------"
- echo -e "\033[32m$geotype数据库文件下载成功!\033[0m"
- fi
- sleep 1
+getcustgeo() {
+ line_break
+ separator_line "="
+ content_line "$UPG_GEO_LINKING"
+ webget "$TMPDIR"/"$geoname" "$custgeolink"
+ if [ "$?" = "1" ]; then
+ content_line "\033[31m$UPG_DOWNLOAD_FAIL\033[0m"
+ error_down
+ else
+ echo "$geoname" | grep -Eq '.mrs|.srs' && {
+ geofile='ruleset/'
+ [ ! -d "$BINDIR"/ruleset ] && mkdir -p "$BINDIR"/ruleset
+ }
+ mv -f "$TMPDIR"/"${geoname}" "$BINDIR"/"${geofile}""${geoname}"
+ content_line "\033[32m${UPG_GEO_OK_PREFIX}${geotype}${UPG_GEO_OK_SUFFIX}\033[0m"
+ separator_line "="
+ fi
+ sleep 1
}
checkcustgeo() {
while true; do
[ "$api_tag" = "latest" ] && api_url=latest || api_url="tags/$api_tag"
[ ! -s "$TMPDIR"/geo.list ] && {
- echo -e "\033[32m正在查找可更新的数据库文件!\033[0m"
+ comp_box "\033[32m$UPG_GEO_FIND_TITLE\033[0m"
webget "$TMPDIR"/github_api https://api.github.com/repos/${project}/releases/${api_url}
release_tag=$(cat "$TMPDIR"/github_api | grep '"tag_name":' | awk -F '"' '{print $4}')
cat "$TMPDIR"/github_api | grep "browser_download_url" | grep -oE 'releases/download.*' | grep -oiE 'geosite.*\.dat"$|country.*\.mmdb"$|.*.mrs|.*.srs' | sed 's|.*/||' | sed 's/"//' >"$TMPDIR"/geo.list
rm -rf "$TMPDIR"/github_api
}
if [ -s "$TMPDIR"/geo.list ]; then
- echo -e "请选择需要更新的数据库文件:"
- echo "-----------------------------------------------"
- cat "$TMPDIR"/geo.list | awk '{print " "NR" "$1}'
- echo -e " 0 返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
+ comp_box "$UPG_GEO_SELECT"
+ awk '{print NR") "$1}' "$TMPDIR/geo.list" |
+ while IFS= read -r line; do
+ content_line "$line"
+ done
+ content_line ""
+ content_line "0) $COMMON_BACK"
+ separator_line "="
+ read -r -p "$COMMON_INPUT> " num
case "$num" in
"" | 0)
break
@@ -561,238 +676,260 @@ checkcustgeo() {
[1-99])
if [ "$num" -le "$(wc -l <"$TMPDIR"/geo.list)" ]; then
geotype=$(sed -n "$num"p "$TMPDIR"/geo.list)
- [ -n "$(echo $geotype | grep -oiE 'GeoSite.*dat')" ] && geoname=GeoSite.dat
- [ -n "$(echo $geotype | grep -oiE 'Country.*mmdb')" ] && geoname=Country.mmdb
- [ -n "$(echo $geotype | grep -oiE '.*(.srs|.mrs)')" ] && geoname=$geotype
+ [ -n "$(echo "$geotype" | grep -oiE 'GeoSite.*dat')" ] && geoname=GeoSite.dat
+ [ -n "$(echo "$geotype" | grep -oiE 'Country.*mmdb')" ] && geoname=Country.mmdb
+ [ -n "$(echo "$geotype" | grep -oiE '.*(.srs|.mrs)')" ] && geoname=$geotype
custgeolink=https://github.com/${project}/releases/download/${release_tag}/${geotype}
getcustgeo
else
errornum
- sleep 1
break
fi
;;
*)
errornum
- sleep 1
- beak
;;
esac
else
- echo -e "\033[31m查找失败,请尽量在服务启动后再使用本功能!\033[0m"
- sleep 1
+ msg_alert "\033[31m$UPG_CORE_CHECK_FAIL_HINT\033[0m"
fi
done
}
# 下载自定义数据库文件
setcustgeo() {
- while true; do
- rm -rf "$TMPDIR"/geo.list
- echo "-----------------------------------------------"
- echo -e "\033[36m此处数据库均源自互联网采集,此处致谢各位开发者!\033[0m"
- echo -e "\033[32m请点击或复制链接前往项目页面查看具体说明!\033[0m"
- echo -e "\033[31m自定义数据库不支持定时任务及小闪存模式!\033[0m"
- echo -e "\033[33m如遇到网络错误请先启动ShellCrash服务!\033[0m"
- echo -e "\033[0m请选择需要更新的数据库项目来源:\033[0m"
- echo "-----------------------------------------------"
- echo -e " 1 \033[36;4mhttps://github.com/MetaCubeX/meta-rules-dat\033[0m (仅限Clash/Mihomo)"
- echo -e " 2 \033[36;4mhttps://github.com/DustinWin/ruleset_geodata\033[0m (仅限Clash/Mihomo)"
- echo -e " 3 \033[36;4mhttps://github.com/DustinWin/ruleset_geodata\033[0m (仅限SingBox-srs)"
- echo -e " 4 \033[36;4mhttps://github.com/DustinWin/ruleset_geodata\033[0m (仅限Mihomo-mrs)"
- echo -e " 5 \033[36;4mhttps://github.com/Loyalsoldier/geoip\033[0m (仅限Clash-GeoIP)"
- echo "-----------------------------------------------"
- echo -e " 9 \033[33m自定义数据库链接 \033[0m"
- echo -e " 0 返回上级菜单"
- read -p "请输入对应数字 > " num
- case "$num" in
- ""|0)
- break
- ;;
- 1)
- project=MetaCubeX/meta-rules-dat
- api_tag=latest
- checkcustgeo
- ;;
- 2)
- project=DustinWin/ruleset_geodata
- api_tag=mihomo-geodata
- checkcustgeo
- ;;
- 3)
- project=DustinWin/ruleset_geodata
- api_tag=sing-box-ruleset
- checkcustgeo
- ;;
- 4)
- project=DustinWin/ruleset_geodata
- api_tag=mihomo-ruleset
- checkcustgeo
- ;;
- 5)
- project=Loyalsoldier/geoip
- api_tag=latest
- checkcustgeo
- ;;
- 9)
- read -p "请输入自定义数据库的链接地址 > " link
- [ -n "$link" ] && custgeolink="$link"
- getgeo
- ;;
- *)
- errornum
- sleep 1
- break
- ;;
- esac
- done
-}
-setgeo() {
- while true; do
- . $CFG_PATH > /dev/null
- [ -n "$cn_mini_v" ] && geo_type_des=精简版 || geo_type_des=全球版
- echo "-----------------------------------------------"
- echo -e "\033[36m请选择需要更新的Geo数据库文件:\033[0m"
- echo -e "\033[36mMihomo内核和SingBox内核的数据库文件不通用\033[0m"
- echo -e "在线数据库最新版本(每日同步上游):\033[32m$GeoIP_v\033[0m"
- echo "-----------------------------------------------"
- echo -e " 1 CN-IP绕过文件(约0.1mb) \033[33m$china_ip_list_v\033[0m"
- echo -e " 2 CN-IPV6绕过文件(约30kb) \033[33m$china_ipv6_list_v\033[0m"
- echo "-----------------------------------------------"
- echo -e " 3 Mihomo精简版GeoIP_cn数据库(约0.1mb) \033[33m$cn_mini_v\033[0m"
- echo -e " 4 Mihomo完整版GeoSite数据库(约5mb) \033[33m$geosite_v\033[0m"
- echo "-----------------------------------------------"
- echo -e " 5 Mihomo-mrs数据库常用包(约1mb,非必要勿用)"
- echo -e " 6 Singbox-srs数据库常用包(约0.8mb,非必要勿用)"
- echo "-----------------------------------------------"
- echo -e " 8 \033[32m自定义数据库文件\033[0m"
- echo -e " 9 \033[31m清理数据库文件\033[0m"
- echo " 0 返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- ""|0)
- break
- ;;
- 1)
- geotype=china_ip_list.txt
- geoname=cn_ip.txt
- getgeo
- ;;
- 2)
- geotype=china_ipv6_list.txt
- geoname=cn_ipv6.txt
- getgeo
- ;;
- 3)
- geotype=cn_mini.mmdb
- geoname=Country.mmdb
- getgeo
- ;;
- 4)
- geotype=geosite.dat
- geoname=GeoSite.dat
- getgeo
- ;;
- 5)
- geotype=mrs.tar.gz
- geoname=mrs.tar.gz
- getgeo
- ;;
- 6)
- geotype=srs.tar.gz
- geoname=srs.tar.gz
- getgeo
- ;;
- 8)
- setcustgeo
- ;;
- 9)
- echo "-----------------------------------------------"
- echo -e "\033[33m这将清理$CRASHDIR目录及/ruleset目录下所有数据库文件!\033[0m"
- echo -e "\033[36m清理后启动服务即可自动下载所需文件~\033[0m"
- echo "-----------------------------------------------"
- read -p "确认清理?[1/0] > " res
- [ "$res" = '1' ] && {
- for file in cn_ip.txt cn_ipv6.txt Country.mmdb GeoSite.dat geoip.db geosite.db;do
- rm -rf $CRASHDIR/$file
- done
- for var in Country_v cn_mini_v china_ip_list_v china_ipv6_list_v geosite_v geoip_cn_v geosite_cn_v mrs_geosite_cn_v srs_geoip_cn_v srs_geosite_cn_v mrs_v srs_v;do
- setconfig $var
- done
- rm -rf $CRASHDIR/ruleset/*
- echo -e "\033[33m所有数据库文件均已清理!\033[0m"
- sleep 1
- }
- ;;
- *)
- errornum
- sleep 1
- break
- ;;
- esac
-done
+ while true; do
+ rm -rf "$TMPDIR"/geo.list
+ comp_box "\033[36m$UPG_GEO_CUSTOM_HINT\033[0m" \
+ "\033[32m$UPG_GEO_CUSTOM_HINT2\033[0m" \
+ "\033[31m$UPG_GEO_CUSTOM_HINT3\033[0m" \
+ "\033[33m$UPG_GEO_CUSTOM_HINT4\033[0m"
+
+ content_line "\033[0m$UPG_GEO_SOURCE_TITLE\033[0m"
+ separator_line "-"
+ content_line "1) \033[36;4mhttps://github.com/MetaCubeX/meta-rules-dat\033[0m"
+ sub_content_line "$UPG_GEO_LOCAL_ONLY1"
+
+ content_line "2) \033[36;4mhttps://github.com/DustinWin/ruleset_geodata\033[0m"
+ sub_content_line "$UPG_GEO_LOCAL_ONLY1"
+
+ content_line "3) \033[36;4mhttps://github.com/DustinWin/ruleset_geodata\033[0m"
+ sub_content_line "$UPG_GEO_LOCAL_ONLY2"
+
+ content_line "4) \033[36;4mhttps://github.com/DustinWin/ruleset_geodata\033[0m"
+ sub_content_line "$UPG_GEO_LOCAL_ONLY3"
+
+ content_line "5) \033[36;4mhttps://github.com/Loyalsoldier/geoip\033[0m"
+ sub_content_line "$UPG_GEO_LOCAL_ONLY4"
+
+ content_line "$UPG_GEO_CUSTOM_LINK"
+ content_line ""
+ content_line "0) $COMMON_BACK"
+ separator_line "="
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ project=MetaCubeX/meta-rules-dat
+ api_tag=latest
+ checkcustgeo
+ ;;
+ 2)
+ project=DustinWin/ruleset_geodata
+ api_tag=mihomo-geodata
+ checkcustgeo
+ ;;
+ 3)
+ project=DustinWin/ruleset_geodata
+ api_tag=sing-box-ruleset
+ checkcustgeo
+ ;;
+ 4)
+ project=DustinWin/ruleset_geodata
+ api_tag=mihomo-ruleset
+ checkcustgeo
+ ;;
+ 5)
+ project=Loyalsoldier/geoip
+ api_tag=latest
+ checkcustgeo
+ ;;
+ 9)
+ line_break
+ read -r -p "$UPG_GEO_LINK_HINT" link
+ [ -n "$link" ] && custgeolink="$link"
+ getgeo
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
}
-#Dashboard
+setgeo() {
+ while true; do
+ . $CFG_PATH >/dev/null
+ [ -n "$cn_mini_v" ] && geo_type_des=$UPG_GEO_TYPE_LITE || geo_type_des=$UPG_GEO_TYPE_FULL
+ comp_box "\033[33m$UPG_GEO_CHOOSE_HINT\033[0m" \
+ "$UPG_GEO_LATEST\033[32m$GeoIP_v\033[0m" \
+ "" \
+ "$UPG_GEO_CHOOSE"
+
+ btm_box "$UPG_GEO_ITEM1 \033[33m$china_ip_list_v\033[0m" \
+ "$UPG_GEO_ITEM2 \033[33m$china_ipv6_list_v\033[0m" \
+ "" \
+ "$UPG_GEO_ITEM3 \033[33m$cn_mini_v\033[0m" \
+ "$UPG_GEO_ITEM4 \033[33m$geosite_v\033[0m" \
+ "" \
+ "$UPG_GEO_ITEM5" \
+ "$UPG_GEO_ITEM6" \
+ "" \
+ "$UPG_GEO_ITEM8" \
+ "$UPG_GEO_ITEM9" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ geotype=china_ip_list.txt
+ geoname=cn_ip.txt
+ getgeo
+ ;;
+ 2)
+ geotype=china_ipv6_list.txt
+ geoname=cn_ipv6.txt
+ getgeo
+ ;;
+ 3)
+ geotype=cn_mini.mmdb
+ geoname=Country.mmdb
+ getgeo
+ ;;
+ 4)
+ geotype=geosite.dat
+ geoname=GeoSite.dat
+ getgeo
+ ;;
+ 5)
+ geotype=mrs.tar.gz
+ geoname=mrs.tar.gz
+ getgeo
+ ;;
+ 6)
+ geotype=srs.tar.gz
+ geoname=srs.tar.gz
+ getgeo
+ ;;
+ 8)
+ setcustgeo
+ ;;
+ 9)
+ while true; do
+ comp_box "\033[33m${UPG_GEO_CLEAN_HINT1_PREFIX}${CRASHDIR}${UPG_GEO_CLEAN_HINT1_SUFFIX}\033[0m" \
+ "$UPG_GEO_CLEAN_HINT2"
+ btm_box "$UPG_GEO_CLEAN_CONFIRM" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " res
+ case "$res" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ for file in cn_ip.txt cn_ipv6.txt Country.mmdb GeoSite.dat geoip.db geosite.db; do
+ rm -rf $CRASHDIR/$file
+ done
+ for var in Country_v cn_mini_v china_ip_list_v china_ipv6_list_v geosite_v geoip_cn_v geosite_cn_v mrs_geosite_cn_v srs_geoip_cn_v srs_geosite_cn_v mrs_v srs_v; do
+ setconfig $var
+ done
+ rm -rf "$CRASHDIR"/ruleset/*
+ msg_alert "\033[33m$UPG_GEO_CLEAN_OK\033[0m"
+ break
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
+}
+
+# Dashboard
getdb() {
dblink="${update_url}/"
- echo "-----------------------------------------------"
- echo "正在连接服务器获取安装文件…………"
+ line_break
+ separator_line "="
+ content_line "$UPG_DB_GETTING"
get_bin "$TMPDIR"/clashdb.tar.gz bin/dashboard/${db_type}.tar.gz
if [ "$?" = "1" ]; then
- echo "-----------------------------------------------"
- echo -e "\033[31m文件下载失败!\033[0m"
- echo "-----------------------------------------------"
+ content_line "\033[31m$UPG_DOWNLOAD_FAIL\033[0m"
error_down
return 1
else
- echo -e "\033[33m下载成功,正在解压文件!\033[0m"
- mkdir -p $dbdir >/dev/null
- tar -zxf "$TMPDIR/clashdb.tar.gz" ${tar_para} -C $dbdir >/dev/null
- [ $? -ne 0 ] && echo "文件解压失败!" && rm -rf "$TMPDIR"/clashfm.tar.gz && exit 1
+ content_line "\033[33m$UPG_DB_DOWNLOAD_OK\033[0m"
+ mkdir -p "$dbdir" >/dev/null
+ tar -zxf "$TMPDIR/clashdb.tar.gz" ${tar_para} -C "$dbdir" >/dev/null
+ if [ $? -ne 0 ]; then
+ content_line "$UPG_EXTRACT_FAIL"
+ separator_line "="
+ line_break
+ sleep 1
+ rm -rf "$TMPDIR"/clashfm.tar.gz
+ exit 1
+ fi
+
#修改默认host和端口
if [ "$db_type" = "clashdb" -o "$db_type" = "meta_db" -o "$db_type" = "zashboard" ]; then
- sed -i "s/127.0.0.1/${host}/g" $dbdir/assets/*.js
- sed -i "s/9090/${db_port}/g" $dbdir/assets/*.js
+ sed -i "s/127.0.0.1/${host}/g" "$dbdir"/assets/*.js
+ sed -i "s/9090/${db_port}/g" "$dbdir"/assets/*.js
elif [ "$db_type" = "meta_xd" ]; then
- sed -i "s/127.0.0.1:9090/${host}:${db_port}/g" $dbdir/_nuxt/*.js
+ sed -i "s/127.0.0.1:9090/${host}:${db_port}/g" "$dbdir"/_nuxt/*.js
else
- sed -i "s/127.0.0.1:9090/${host}:${db_port}/g" $dbdir/*.html
+ sed -i "s/127.0.0.1:9090/${host}:${db_port}/g" "$dbdir"/*.html
fi
#写入配置文件
setconfig hostdir "'$hostdir'"
- echo "-----------------------------------------------"
- echo -e "\033[32m面板安装成功!\033[36m如未生效,请使用【Ctrl+F5】强制刷新浏览器!!!\033[0m"
+ content_line "\033[32m$UPG_DB_OK\033[0m"
+ content_line "\033[36m$UPG_DB_REFRESH_HINT\033[0m"
+ separator_line "="
+ sleep 1
rm -rf "$TMPDIR"/clashdb.tar.gz
fi
sleep 1
}
dbdir() {
- if [ -f /www/clash/CNAME -o -f "$CRASHDIR"/ui/CNAME ]; then
- echo "-----------------------------------------------"
- echo -e "\033[31m检测到您已经安装过本地面板了!\033[0m"
- echo "-----------------------------------------------"
- read -p "是否升级/覆盖安装?[1/0] > " res
+ if [ -f /www/clash/CNAME ] || [ -f "$CRASHDIR"/ui/CNAME ]; then
+ comp_box "\033[33m$UPG_DB_INSTALLED\033[0m"
+ btm_box "$UPG_DB_UPGRADE" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " res
if [ "$res" = 1 ]; then
rm -rf "$BINDIR"/ui
[ -f /www/clash/CNAME ] && rm -rf /www/clash && dbdir=/www/clash
[ -f "$CRASHDIR"/ui/CNAME ] && rm -rf "$CRASHDIR"/ui && dbdir="$CRASHDIR"/ui
getdb
else
- echo -e "\033[33m安装已取消!\033[0m"
+ msg_alert "\033[33m$UPG_DB_CANCEL\033[0m"
return 1
fi
- elif [ -w /www -a -n "$(pidof nginx)" ]; then
- echo "-----------------------------------------------"
- echo -e "请选择面板\033[33m安装目录:\033[0m"
- echo "-----------------------------------------------"
- echo -e " 1 在${CRASHDIR}/ui目录安装"
- echo -e " 2 在/www/clash目录安装"
- echo "-----------------------------------------------"
- echo " 0 返回上级菜单"
- read -p "请输入对应数字 > " num
+ elif [ -w /www ] && [ -n "$(pidof nginx)" ]; then
+ comp_box "$UPG_DB_DIR_SELECT"
+ btm_box "${UPG_DB_DIR_1_PREFIX}${CRASHDIR}${UPG_DB_DIR_1_SUFFIX}" \
+ "$UPG_DB_DIR_2" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
case "$num" in
"" | 0)
return 0
@@ -809,7 +946,6 @@ dbdir() {
;;
*)
errornum
- sleep 1
return 1
;;
esac
@@ -822,23 +958,22 @@ dbdir() {
setdb() {
while true; do
- echo "-----------------------------------------------"
- echo -e "\033[36m安装本地版dashboard管理面板\033[0m"
- echo -e "\033[32m打开管理面板的速度更快且更稳定\033[0m"
- echo "-----------------------------------------------"
- echo -e "请选择面板\033[33m安装类型:\033[0m"
- echo "-----------------维护中------------------------"
- echo -e " 1 安装\033[32mzashboard面板\033[0m(约2.2mb)"
- echo -e " 2 安装\033[32mMetaXD面板\033[0m(约1.5mb)"
- echo -e " 3 安装\033[32mYacd-Meta魔改面板\033[0m(约1.7mb)"
- echo "---------------已停止维护----------------------"
- echo -e " 4 安装\033[32m基础面板\033[0m(约500kb)"
- echo -e " 5 安装\033[32mMeta基础面板\033[0m(约800kb)"
- echo -e " 6 安装\033[32mYacd面板\033[0m(约1.1mb)"
- echo "-----------------------------------------------"
- echo -e " 9 卸载\033[33m本地面板\033[0m"
- echo " 0 返回上级菜单"
- read -p "请输入对应数字 > " num
+ comp_box "\033[36m$UPG_DB_TITLE\033[0m" \
+ "\033[32m$UPG_DB_TITLE2\033[0m" \
+ "" \
+ "$UPG_DB_SELECT"
+ btm_box "$UPG_DB_WIP" \
+ "$UPG_DB_INSTALL_1" \
+ "$UPG_DB_INSTALL_2" \
+ "$UPG_DB_INSTALL_3" \
+ "$UPG_DB_OLD" \
+ "$UPG_DB_INSTALL_4" \
+ "$UPG_DB_INSTALL_5" \
+ "$UPG_DB_INSTALL_6" \
+ "$UPG_DB_UNINSTALL" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
case "$num" in
"" | 0)
break
@@ -870,215 +1005,269 @@ setdb() {
dbdir
;;
9)
- read -p "确认卸载本地面板?(1/0) > " res
- if [ "$res" = 1 ]; then
- rm -rf /www/clash
- rm -rf "$CRASHDIR"/ui
- rm -rf "$BINDIR"/ui
- echo "-----------------------------------------------"
- echo -e "\033[31m面板已经卸载!\033[0m"
- sleep 1
- fi
+ while true; do
+ comp_box "$UPG_DB_UNINSTALL_CONFIRM"
+ btm_box "$UPG_DB_UNINSTALL_YES" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " res
+ case "$res" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ rm -rf /www/clash
+ rm -rf "$CRASHDIR"/ui
+ rm -rf "$BINDIR"/ui
+ msg_alert "\033[31m$UPG_DB_UNINSTALL_OK\033[0m"
+ break
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
;;
*)
errornum
- sleep 1
- break
;;
esac
done
}
-#根证书
-getcrt(){
- echo "-----------------------------------------------"
- echo "正在连接服务器获取安装文件…………"
- get_bin "$TMPDIR"/ca-certificates.crt bin/fix/ca-certificates.crt
- if [ "$?" = "1" ];then
- echo "-----------------------------------------------"
- echo -e "\033[31m文件下载失败!\033[0m"
- error_down
- else
- echo "-----------------------------------------------"
- [ "$systype" = 'mi_snapshot' ] && cp -f "$TMPDIR"/ca-certificates.crt $CRASHDIR/tools #镜像化设备特殊处理
- [ -f $openssldir/certs ] && rm -rf $openssldir/certs #如果certs不是目录而是文件则删除并创建目录
- mkdir -p $openssldir/certs
- mv -f "$TMPDIR"/ca-certificates.crt $crtdir
- webget /dev/null https://baidu.com echooff rediron skipceroff
- if [ "$?" = "1" ];then
- export CURL_CA_BUNDLE=$crtdir
- echo "export CURL_CA_BUNDLE=$crtdir" >> /etc/profile
- fi
- echo -e "\033[32m证书安装成功!\033[0m"
- sleep 1
- fi
+# 根证书
+getcrt() {
+ line_break
+ separator_line "="
+ content_line "$UPG_DB_GETTING"
+ get_bin "$TMPDIR"/ca-certificates.crt bin/fix/ca-certificates.crt echooff
+ if [ "$?" = "1" ]; then
+ content_line "\033[31m$UPG_DOWNLOAD_FAIL\033[0m"
+ error_down
+ else
+ [ "$systype" = 'mi_snapshot' ] && cp -f "$TMPDIR"/ca-certificates.crt "$CRASHDIR"/tools #镜像化设备特殊处理
+ [ -f "$openssldir"/certs ] && rm -rf "$openssldir"/certs #如果certs不是目录而是文件则删除并创建目录
+ mkdir -p "$openssldir"/certs
+ mv -f "$TMPDIR"/ca-certificates.crt "$crtdir"
+ webget /dev/null https://baidu.com echooff rediron skipceroff
+ if [ "$?" = "1" ]; then
+ export CURL_CA_BUNDLE="$crtdir"
+ echo "export CURL_CA_BUNDLE=$crtdir" >>/etc/profile
+ fi
+ content_line "\033[32m$UPG_CRT_DB_OK\033[0m"
+ separator_line "="
+ sleep 1
+ fi
}
-setcrt(){
- openssldir="$(openssl version -d 2>&1 | awk -F '"' '{print $2}')"
- if [ -d "$openssldir/certs/" ];then
- crtdir="$openssldir/certs/ca-certificates.crt"
- else
- crtdir="/etc/ssl/certs/ca-certificates.crt"
- fi
- if [ -n "$openssldir" ];then
- echo "-----------------------------------------------"
- echo -e "\033[36m安装/更新本地根证书文件(ca-certificates.crt)\033[0m"
- echo -e "\033[33m用于解决证书校验错误,x509报错等问题\033[0m"
- echo -e "\033[31m无上述问题的设备请勿使用!\033[0m"
- echo "-----------------------------------------------"
- [ -f "$crtdir" ] && echo -e "\033[33m检测到系统已经存在根证书文件($crtdir)了!\033[0m\n-----------------------------------------------"
- read -p "是否覆盖更新?(1/0) > " res
- if [ -z "$res" ];then
- errornum
- elif [ "$res" = '0' ]; then
- i=
- elif [ "$res" = '1' ]; then
- getcrt
- else
- errornum
- fi
- else
- echo "-----------------------------------------------"
- echo -e "\033[33m设备可能尚未安装openssl,无法安装证书文件!\033[0m"
- sleep 1
- fi
+setcrt() {
+ while true; do
+ openssldir="$(openssl version -d 2>&1 | awk -F '"' '{print $2}')"
+ if [ -d "$openssldir/certs/" ]; then
+ crtdir="$openssldir/certs/ca-certificates.crt"
+ else
+ crtdir="/etc/ssl/certs/ca-certificates.crt"
+ fi
+
+ if [ -n "$openssldir" ]; then
+ line_break
+ separator_line "="
+ content_line "$UPG_CRT_TITLE1"
+ content_line "\033[33m$UPG_CRT_TITLE2\033[0m"
+ content_line "\033[31m$UPG_CRT_TITLE3\033[0m"
+ if [ -f "$crtdir" ]; then
+ content_line ""
+ content_line "\033[33m$UPG_CRT_EXISTS\033[0m"
+ content_line "\033[33m($crtdir)\033[0m"
+ fi
+ separator_line "="
+
+ if [ -f "$crtdir" ]; then
+ content_line "$UPG_CRT_UPDATE"
+ else
+ content_line "$UPG_CRT_INSTALL"
+ fi
+ content_line "0) $COMMON_BACK"
+ separator_line "="
+ read -r -p "$COMMON_INPUT> " res
+ case "$res" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ getcrt
+ break
+ ;;
+ *)
+ errornum
+ continue
+ ;;
+ esac
+
+ else
+ msg_alert "\033[33m$UPG_CRT_WARN\033[0m"
+ break
+ fi
+
+ done
}
# 写入配置文件
saveserver() {
- setconfig update_url "'$update_url'"
- setconfig url_id $url_id
- setconfig release_type $release_type
- version_new=''
- echo "-----------------------------------------------"
- echo -e "\033[32m源地址切换成功!\033[0m"
+ setconfig update_url "'$update_url'"
+ setconfig url_id "$url_id"
+ setconfig release_type "$release_type"
+ version_new=''
+ msg_alert -t 0 "\033[32m$UPG_SOURCE_SWITCH_OK\033[0m"
}
# 安装源
setserver() {
- while true; do
- [ -z "$release_type" ] && release_name=未指定
- [ -n "$release_type" ] && release_name="$release_type(回退)"
- [ "$release_type" = stable ] && release_name=稳定版
- [ "$release_type" = master ] && release_name=公测版
- [ "$release_type" = dev ] && release_name=开发版
- [ -n "$url_id" ] && url_name=$(grep "$url_id" "$CRASHDIR"/configs/servers.list 2>/dev/null | awk '{print $2}') || url_name="$update_url"
-
- echo "-----------------------------------------------"
- echo -e "\033[30;47m切换ShellCrash版本及更新源地址\033[0m"
- echo -e "当前版本:\033[4;33m$release_name\033[0m 当前源:\033[4;32m$url_name\033[0m"
- echo "-----------------------------------------------"
- grep -E "^1|$release_name" "$CRASHDIR"/configs/servers.list | awk '{print " "NR" "$2}'
- echo "-----------------------------------------------"
- echo -e " a 切换至\033[32m稳定版-stable\033[0m"
- echo -e " b 切换至\033[36m公测版-master\033[0m"
- echo -e " c 切换至\033[33m开发版-dev\033[0m"
- echo "-----------------------------------------------"
- echo -e " d 自定义源地址(用于本地源或自建源)"
- echo -e " e \033[31m版本回退\033[0m"
- echo -e " 0 返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入对应字母或数字 > " num
- case "$num" in
- ""|0)
- checkupdate=false
- break
- ;;
- [1-99])
- url_id_new=$(grep -E "^1|$release_name" "$CRASHDIR"/configs/servers.list | sed -n "$num"p | awk '{print $1}')
- if [ -z "$url_id_new" ];then
- errornum
- sleep 1
- continue
- elif [ "$url_id_new" -ge 200 ];then
- update_url=$(grep -E "^1|$release_name" "$CRASHDIR"/configs/servers.list | sed -n "$num"p | awk '{print $3}')
- url_id=''
- saveserver
- break
- else
- url_id=$url_id_new
- update_url=''
- saveserver
- break
- fi
- unset url_id_new
- ;;
- a)
- release_type=stable
- [ -z "$url_id" ] && url_id=101
- saveserver
- ;;
- b)
- release_type=master
- [ -z "$url_id" ] && url_id=101
- saveserver
- ;;
- c)
- echo "-----------------------------------------------"
- echo -e "\033[33m开发版未经过妥善测试,可能依然存在大量bug!!!\033[0m"
- echo -e "\033[36m如果你没有足够的耐心或者测试经验,切勿使用此版本!\033[0m"
- echo -e "请务必加入我们的讨论组:\033[32;4mhttps://t.me/ShellClash\033[0m"
- read -p "是否依然切换到开发版?(1/0) > " res
- if [ "$res" = 1 ];then
- release_type=dev
- [ -z "$url_id" ] && url_id=101
- saveserver
- fi
- ;;
- d)
- echo "-----------------------------------------------"
- read -p "请输入个人源路径 > " update_url
- if [ -z "$update_url" ];then
- echo "-----------------------------------------------"
- echo -e "\033[31m取消输入,返回上级菜单\033[0m"
- else
- url_id=''
- release_type=''
- saveserver
- fi
- ;;
- e)
- echo "-----------------------------------------------"
- if [ -n "$url_id" ] && [ "$url_id" -lt 200 ];then
- echo -ne "\033[32m正在获取版本信息!\033[0m\r"
- . "$CRASHDIR"/libs/web_get_lite.sh
- web_get_lite https://github.com/juewuy/ShellCrash/tags | grep -o 'releases/tag/.*data'|awk -F '/' '{print $3}'|sed 's/".*//g' > "$TMPDIR"/tags
- if [ "$?" = "0" ];then
- echo -e "\033[31m请选择想要回退至的具体版本:\033[0m"
- cat "$TMPDIR"/tags | awk '{print " "NR" "$1}'
- echo -e " 0 返回上级菜单"
- read -p "请输入对应数字 > " num
- if [ -z "$num" -o "$num" = 0 ]; then
- continue
- elif [ $num -le $(cat "$TMPDIR"/tags 2>/dev/null | awk 'END{print NR}') ]; then
- release_type=$(cat "$TMPDIR"/tags | awk '{print $1}' | sed -n "$num"p)
- update_url=''
- saveserver
- else
- echo "-----------------------------------------------"
- errornum
- sleep 1
- continue
- fi
- else
- echo "-----------------------------------------------"
- echo -e "\033[31m版本回退信息获取失败,请尝试更换其他安装源!\033[0m"
- sleep 1
- continue
- fi
- rm -rf "$TMPDIR"/tags
- else
- echo -e "\033[31m当前源不支持版本回退,请尝试更换其他安装源!\033[0m"
- sleep 1
- continue
- fi
- ;;
- *)
- errornum
- sleep 1
- break
- ;;
- esac
- done
+ while true; do
+ line_break
+ LISTFILE="$CRASHDIR"/configs/servers_"$i18n".list
+ [ -z "$release_type" ] && release_name=$UPG_SOURCE_UNSET
+ [ -n "$release_type" ] && release_name="$release_type$UPG_SOURCE_ROLLBACK_TAG"
+ [ "$release_type" = stable ] && release_name=$UPG_SOURCE_STABLE_TEXT
+ [ "$release_type" = master ] && release_name=$UPG_SOURCE_MASTER_TEXT
+ [ "$release_type" = dev ] && release_name=$UPG_SOURCE_DEV_TEXT
+ [ -n "$url_id" ] && url_name=$(grep "$url_id" "$LISTFILE" 2>/dev/null | awk '{print $2}') || url_name="$update_url"
+
+ comp_box "\033[30;47m$UPG_SOURCE_TITLE\033[0m" \
+ "" \
+ "$UPG_SOURCE_CUR_VER\033[4;33m$release_name\033[0m" \
+ "$UPG_SOURCE_CUR_URL\n\033[4;32m$url_name\033[0m"
+
+ grep -E "^1|^2" "$LISTFILE" |
+ awk '{print NR") "$2}' |
+ while IFS= read -r line; do
+ content_line "$line"
+ done
+
+ btm_box "" \
+ "$UPG_SOURCE_SWITCH_STABLE" \
+ "$UPG_SOURCE_SWITCH_MASTER" \
+ "$UPG_SOURCE_SWITCH_DEV" \
+ "" \
+ "$UPG_SOURCE_CUSTOM" \
+ "$UPG_SOURCE_ROLLBACK" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 0)
+ checkupdate=false
+ break
+ ;;
+ [1-99])
+ url_id_new=$(grep -E "^1|$release_name" "$LISTFILE" | sed -n "$num"p | awk '{print $1}')
+ if [ -z "$url_id_new" ]; then
+ errornum
+ continue
+ elif [ "$url_id_new" -ge 200 ]; then
+ update_url=$(grep -E "^1|$release_name" "$LISTFILE" | sed -n "$num"p | awk '{print $3}')
+ url_id=''
+ saveserver
+ break
+ else
+ url_id=$url_id_new
+ update_url=''
+ saveserver
+ break
+ fi
+ unset url_id_new
+ ;;
+ a)
+ release_type=stable
+ [ -z "$url_id" ] && url_id=101
+ saveserver
+ ;;
+ b)
+ release_type=master
+ [ -z "$url_id" ] && url_id=101
+ saveserver
+ ;;
+ c)
+ while true; do
+ comp_box "\033[33m$UPG_SOURCE_DEV_WARN1\033[0m" \
+ "\033[33m$UPG_SOURCE_DEV_WARN2\033[0m" \
+ "$UPG_SOURCE_DEV_WARN3"
+ content_line "$UPG_SOURCE_DEV_CONFIRM"
+ separator_line "-"
+ btm_box "$UPG_SOURCE_DEV_YES" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " res
+ case "$res" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ release_type=dev
+ [ -z "$url_id" ] && url_id=101
+ saveserver
+ break
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
+ ;;
+ d)
+ comp_box "\033[36m$UPG_SOURCE_CUSTOM_HINT\033[0m" \
+ "$UPG_CUSTOM_CORE_LINK_HINT3"
+ read -r -p "$UPG_SOURCE_CUSTOM_INPUT" update_url
+ if [ "$update_url" = 0 ]; then
+ continue
+ elif [ ! -z "$update_url" ]; then
+ url_id=''
+ release_type=''
+ saveserver
+ fi
+ ;;
+ e)
+ if [ -n "$url_id" ] && [ "$url_id" -lt 200 ]; then
+ line_break
+ separator_line "="
+ content_line "\033[32m$UPG_SOURCE_VER_GETTING\033[0m"
+ . "$CRASHDIR"/libs/web_get_lite.sh
+ list=$(web_get_lite https://api.github.com/repos/juewuy/ShellCrash/tags | grep -E '"name": "[0-9]' | cut -d '"' -f4)
+ if [ "$?" = "0" ]; then
+ content_line "\033[32m$UPG_SOURCE_VER_OK\033[0m"
+ separator_line "="
+
+ line_break
+ separator_line "="
+ content_line "\033[31m$UPG_SOURCE_ROLLBACK_SELECT\033[0m"
+ list_box "$list"
+ btm_box "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ if [ -z "$num" ] || [ "$num" = 0 ]; then
+ continue
+ elif [ "$num" -le $(echo "$list" | awk 'END{print NR}') ]; then
+ release_type=$(echo "$list" | sed -n "$num"p)
+ update_url=''
+ saveserver
+ else
+ errornum
+ continue
+ fi
+ else
+ content_line "\033[31m$UPG_SOURCE_ROLLBACK_FAIL\033[0m"
+ separator_line "="
+ sleep 1
+ continue
+ fi
+ rm -rf "$TMPDIR"/tags
+ else
+ msg_alert "\033[31m$UPG_SOURCE_ROLLBACK_NOTSUP\033[0m" \
+ "\033[31m$UPG_SOURCE_ROLLBACK_HINT\033[0m"
+ continue
+ fi
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
}
diff --git a/scripts/menus/bot_tg.sh b/scripts/menus/bot_tg.sh
index 15a53181..d411e095 100644
--- a/scripts/menus/bot_tg.sh
+++ b/scripts/menus/bot_tg.sh
@@ -4,10 +4,13 @@
. "$CRASHDIR"/libs/web_json.sh
. "$CRASHDIR"/libs/set_config.sh
. "$CRASHDIR"/libs/web_get_lite.sh
+. "$CRASHDIR"/libs/i18n.sh
. "$CRASHDIR"/menus/running_status.sh
. "$CRASHDIR"/configs/gateway.cfg
. "$CRASHDIR"/configs/ShellCrash.cfg
+load_lang bot_tg
+
TMPDIR='/tmp/ShellCrash'
API="https://api.telegram.org/bot$TG_TOKEN"
STATE_FILE="$TMPDIR/tgbot_state"
@@ -16,66 +19,66 @@ 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
+ 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
+ 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\"}"
+ web_json_post "$API/sendMessage" "{\"chat_id\":\"$TG_CHATID\",\"text\":\"$TEXT\",\"parse_mode\":\"Markdown\"}"
}
send_help(){
TEXT=$(cat </dev/null 2>&1;then
- CURL_KB=$(cat </dev/null 2>&1;then
+ CURL_KB=$(cat < "$LOGFILE"
+ [ -z "$redir_mod_bf" ] && redir_mod_bf='Redir'
+ redir_mod=$redir_mod_bf
+ setconfig redir_mod $redir_mod
+ "$CRASHDIR"/start.sh start_firewall
+ echo "$BOT_TG_FW_ENABLED*$redir_mod_bf*$BOT_TG_FW_ENABLED_SUFFIX" > "$LOGFILE"
}
do_stop_fw(){
- redir_mod_bf=$redir_mod
- redir_mod='纯净模式'
- setconfig redir_mod $redir_mod
- "$CRASHDIR"/start.sh stop_firewall
- echo "ShellCrash 已切换到纯净模式!" > "$LOGFILE"
+ redir_mod_bf=$redir_mod
+ firewall_area=4
+ setconfig firewall_area 4
+ "$CRASHDIR"/start.sh stop_firewall
+ echo "$BOT_TG_SWITCH_PURE" > "$LOGFILE"
}
do_restart(){
"$CRASHDIR"/start.sh restart
- echo "ShellCrash 服务已重启!" > "$LOGFILE"
+ echo "$BOT_TG_SERVICE_RESTARTED" > "$LOGFILE"
}
do_set_sub(){
#echo "$1" "$2" >> "$CRASHDIR"/configs/providers.cfg
- echo "错误,还未完成的功能!" > "$LOGFILE"
+ echo "$BOT_TG_UNFINISHED" > "$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
+ 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 "$BOT_TG_SEND_CORE ${corename} $BOT_TG_SEND_CORE_SUFFIX"
+ ;;
+ "ts_up_bak")
+ FILE_TYPE=2
+ send_msg "$BOT_TG_SEND_BAK"
+ ;;
+ "ts_up_ccf")
+ FILE_TYPE=3
+ send_msg "$BOT_TG_SEND_CFG .${config_type} $BOT_TG_SEND_CFG_SUFFIX"
+ ;;
+ esac
}
### --- 轮询主进程 --- ###
polling(){
- while true; do
- UPDATES=$(web_get_lite "$API/getUpdates?timeout=25&offset=$OFFSET")
+ 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 [ "$redir_mod" = '纯净模式' ];then
- do_start_fw
- send_msg "已切换到$redir_mod_bf!"
- else
- send_msg "当前已经是$redir_mod!"
- fi
- send_menu
- continue
- ;;
- "stop_redir")
- if [ "$redir_mod" != '纯净模式' ];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
+ 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 "$BOT_TG_SWITCH_TO$redir_mod_bf!"
+ else
+ send_msg "$BOT_TG_ALREADY$redir_mod!"
+ fi
+ send_menu
+ continue
+ ;;
+ "stop_redir")
+ if [ "$firewall_area" != 4 ];then
+ do_stop_fw
+ send_msg "$BOT_TG_SWITCH_PURE"
+ else
+ send_msg "$BOT_TG_ALREADY_PURE"
+ fi
+ send_menu
+ continue
+ ;;
+ "restart")
+ do_restart
+ send_msg "$BOT_TG_SERVICE_RESTARTED_SHORT"
+ sleep 10
+ send_menu
+ continue
+ ;;
+ "readlog")
+ send_msg "$BOT_TG_LOG_CONTENT\n\`\`\`$(grep -v "$BOT_TG_TASK_WORD" $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 "$BOT_TG_INPUT_SUB"
+ continue
+ ;;
+ ts_*)
+ transport
+ continue
+ ;;
+ esac
- ### --- 处理订阅输入 --- ###
- TEXT=$(echo "$UPDATES" | grep -o '"text":"[^"]*"' | tail -n1 | sed 's/.*"text":"//;s/"$//')
+ ### --- 处理订阅输入 --- ###
+ 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
+ if [ "$(cat "$STATE_FILE" 2>/dev/null)" = "await_sub" ]; then
+ echo "" > "$STATE_FILE"
+ do_set_sub "$TEXT"
+ send_msg "$BOT_TG_SUB_UPDATED\n$(cat "$LOGFILE")"
+ send_menu
+ continue
+ fi
- ### 处理命令 ###
- case "$TEXT" in
- /crash)
- send_menu
- ;;
- /"$my_alias")
- send_menu
- ;;
- /help)
- send_help
- ;;
- esac
+ ### 处理命令 ###
+ case "$TEXT" in
+ /crash)
+ send_menu
+ ;;
+ /"$my_alias")
+ send_menu
+ ;;
+ /help)
+ send_help
+ ;;
+ esac
- done
+ done
}
[ "$TG_menupush" = ON ] && send_menu
diff --git a/scripts/menus/bot_tg_bind.sh b/scripts/menus/bot_tg_bind.sh
index 6992dccc..eb630d8a 100644
--- a/scripts/menus/bot_tg_bind.sh
+++ b/scripts/menus/bot_tg_bind.sh
@@ -2,58 +2,59 @@
. "$CRASHDIR"/libs/web_get_lite.sh
+load_lang bot_tg
+
private_bot() {
- echo "-----------------------------------------------"
- echo -e "请先通过 \033[32;4mhttps://t.me/BotFather\033[0m 申请TG机器人并获取其\033[36mAPI TOKEN\033[0m"
- echo "-----------------------------------------------"
- read -p "请输入你获取到的API TOKEN > " TOKEN
- echo "-----------------------------------------------"
- echo -e "请向\033[32m你申请的机器人\033[33m而不是BotFather!\033[0m"
- url_tg=https://api.telegram.org/bot${TOKEN}/getUpdates
-}
-public_bot() {
- echo -e "请向机器人:\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
- echo -e "\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/.*-//')
- echo -e "发送此秘钥: \033[30;46m$public_key\033[0m"
- echo "-----------------------------------------------"
- read -p "我已经发送完成(1/0) > " res
- if [ "$res" = 1 ]; then
- get_chatid
- [ -z "$chat_ID" ] && [ "$TOKEN" != 'publictoken' ] && {
- echo -e "\033[31m无法获取对话ID,请返回重新设置或手动输入ChatID!\033[0m"
- echo -e "通常访问 \033[32;4m$url_tg\033[0m \n\033[36m即可看到ChatID\033[0m"
- read -p "请手动输入ChatID > " chat_ID
- }
- if echo "$chat_ID" | grep -qE '^[0-9]{8,}$'; then
- return 0
- else
- echo -e "\033[31m无法获取对话ID,请重新配置!\033[0m"
- sleep 1
- return 1
- fi
- fi
+ comp_box "$BOT_TG_PRIVATE_HINT"
+ read -r -p "$BOT_TG_INPUT_TOKEN> " TOKEN
+ url_tg=https://api.telegram.org/bot${TOKEN}/getUpdates
+
+ top_box "$BOT_TG_PRIVATE_TOP"
}
+public_bot() {
+ comp_box "$BOT_TG_PUBLIC_HINT"
+ 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 "$BOT_TG_SET_DONE" 32
+}
+
+get_chatid() {
+ i=1
+ chat_ID=''
+ while [ $i -le 3 ] && [ -z "$chat_ID" ]; do
+ sleep 1
+ comp_box "\033[33m$BOT_TG_CHATID_RETRY_PREFIX $i $BOT_TG_CHATID_RETRY_SUFFIX\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 "$BOT_TG_SEND_KEY \033[30;46m$public_key\033[0m"
+ read -r -p "$BOT_TG_SENT_CONFIRM(1/0)> " res
+ if [ "$res" = 1 ]; then
+ get_chatid
+ [ -z "$chat_ID" ] && [ "$TOKEN" != 'publictoken' ] && {
+ comp_box "\033[31m$BOT_TG_CHATID_FAIL\033[0m" \
+ "$BOT_TG_CHATID_MANUAL_HINT \033[32;4m$url_tg\033[0m \n\033[36m$BOT_TG_CHATID_MANUAL_HINT2\033[0m"
+ read -r -p "$BOT_TG_INPUT_CHATID> " chat_ID
+ }
+ if echo "$chat_ID" | grep -qE '^[0-9]{8,}$'; then
+ return 0
+ else
+ msg_alert "\033[31m$BOT_TG_CHATID_RECONFIG\033[0m"
+ return 1
+ fi
+ fi
+}
diff --git a/scripts/menus/bot_tg_service.sh b/scripts/menus/bot_tg_service.sh
index d5ea1b71..e02f1717 100644
--- a/scripts/menus/bot_tg_service.sh
+++ b/scripts/menus/bot_tg_service.sh
@@ -1,16 +1,16 @@
-
+
. "$CRASHDIR"/libs/set_cron.sh
bot_tg_start(){
- . "$CRASHDIR"/starts/start_legacy.sh
- start_legacy "$CRASHDIR/menus/bot_tg.sh" 'bot_tg'
+ . "$CRASHDIR"/starts/start_legacy.sh
+ start_legacy "$CRASHDIR/menus/bot_tg.sh" 'bot_tg'
}
bot_tg_stop(){
- cronload | grep -q 'TG_BOT' && cronset 'TG_BOT'
- [ -f "$TMPDIR/bot_tg.pid" ] && kill -TERM "$(cat "$TMPDIR/bot_tg.pid")" 2>/dev/null
- killall bot_tg.sh 2>/dev/null
- rm -f "$TMPDIR/bot_tg.pid"
+ cronload | grep -q 'TG_BOT' && cronset 'TG_BOT'
+ [ -f "$TMPDIR/bot_tg.pid" ] && kill -TERM "$(cat "$TMPDIR/bot_tg.pid")" 2>/dev/null
+ 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守护进程"
+ cronset 'ShellCrash-TG_BOT' "* * * * * /bin/sh $CRASHDIR/starts/start_legacy_wd.sh bot_tg #ShellCrash-TG_BOT"
}
diff --git a/scripts/menus/check_port.sh b/scripts/menus/check_port.sh
index 1a3c288f..5d5f1acd 100644
--- a/scripts/menus/check_port.sh
+++ b/scripts/menus/check_port.sh
@@ -1,17 +1,49 @@
#!/bin/sh
# Copyright (C) Juewuy
-check_port(){
- if [ "$1" -gt 65535 -o "$1" -le 1 ]; then
- echo -e "\033[31m输入错误!请输入正确的数值(1-65535)!\033[0m"
- return 1
- elif [ -n "$(echo "|$mix_port|$redir_port|$dns_port|$db_port|" | grep "|$1|")" ]; then
- echo -e "\033[31m输入错误!请不要输入重复的端口!\033[0m"
- return 1
- elif [ -n "$(netstat -ntul | grep -E ":$1[[:space:]]")" ]; then
- echo -e "\033[31m当前端口已被其他进程占用,请重新输入!\033[0m"
- return 1
- else
- return 0
- fi
+load_lang check_port
+
+_get_netstat_cmd() {
+ case "$1" in
+ tcp) echo "netstat -ntl" ;;
+ udp) echo "netstat -nul" ;;
+ *) echo "netstat -ntul" ;;
+ esac
+}
+
+check_port() {
+ local port="$1"
+ local protocol="${2:-all}"
+
+ if [ "$port" -gt 65535 ] || [ "$port" -le 1 ]; then
+ msg_alert "\033[31m$CHECK_PORT_RANGE_ERR\033[0m"
+ return 1
+ fi
+
+ local check_cmd
+ check_cmd=$(_get_netstat_cmd "$protocol")
+
+ if $check_cmd 2>/dev/null | grep -q ":${port}[[:space:]]"; then
+ msg_alert "\033[31m$CHECK_PORT_OCCUPIED_ERR\033[0m"
+ return 1
+ fi
+
+ return 0
+}
+
+check_port_with_info() {
+ local port="$1"
+ local protocol="${2:-all}"
+ local check_cmd
+ check_cmd=$(_get_netstat_cmd "$protocol")
+
+ local conflict_line
+ conflict_line=$($check_cmd 2>/dev/null | grep ":${port}[[:space:]]" | head -n 1)
+
+ if [ -n "$conflict_line" ]; then
+ echo "$conflict_line"
+ return 1
+ fi
+
+ return 0
}
diff --git a/scripts/menus/common.sh b/scripts/menus/common.sh
new file mode 100644
index 00000000..983c787c
--- /dev/null
+++ b/scripts/menus/common.sh
@@ -0,0 +1,87 @@
+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_success() {
+ msg_alert "\033[32m$COMMON_SUCCESS\033[0m"
+}
+
+common_failed() {
+ msg_alert "\033[32m$COMMON_FAILED\033[0m"
+}
+
+# =================================================
+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
+}
diff --git a/scripts/menus/ddns.sh b/scripts/menus/ddns.sh
index b1d97a87..0b50986d 100644
--- a/scripts/menus/ddns.sh
+++ b/scripts/menus/ddns.sh
@@ -1,183 +1,226 @@
#! /bin/bash
# Copyright (C) Juewuy
+load_lang ddns
-ddns_menu(){
- echo -----------------------------------------------
- echo -e "\033[30;46m欢迎使用DDNS!\033[0m"
- load_ddns
+ddns_menu() {
+ top_box "\033[30;46m$DDNS_WELCOME\033[0m"
+ load_ddns
}
+
add_ddns() {
- cat >>"$ddns_dir" <>"$ddns_dir" </dev/null 2>&1 &
- sleep 3
- echo 服务已经添加!
+ /usr/lib/ddns/dynamic_dns_updater.sh -S "$service" start >/dev/null 2>&1 &
+ sleep 3
+ msg_alert "$DDNS_ADD_DONE"
}
+
set_ddns() {
- echo -----------------------------------------------
- read -p "请输入你的域名 > " str
- [ -z "$str" ] && domain="$domain" || domain="$str"
- echo -----------------------------------------------
- read -p "请输入用户名或邮箱 > " str
- [ -z "$str" ] && username="$username" || username="$str"
- echo -----------------------------------------------
- read -p "请输入密码或令牌秘钥 > " str
- [ -z "$str" ] && password="$password" || password="$str"
- echo -----------------------------------------------
- read -p "请输入检测更新间隔(单位:分钟;默认为10) > " check_interval
- [ -z "$check_interval" ] || [ "$check_interval" -lt 1 -o "$check_interval" -gt 1440 ] && check_interval=10
- echo -----------------------------------------------
- read -p "请输入强制更新间隔(单位:小时;默认为24) > " force_interval
- [ -z "$force_interval" ] || [ "$force_interval" -lt 1 -o "$force_interval" -gt 240 ] && force_interval=24
- echo -----------------------------------------------
- echo -e "请核对如下信息:"
- echo -e "服务商: \033[32m$service\033[0m"
- echo -e "域名: \033[32m$domain\033[0m"
- echo -e "用户名: \033[32m$username\033[0m"
- echo -e "检测间隔: \033[32m$check_interval\033[0m"
- echo -----------------------------------------------
- read -p "确认添加?(1/0) > " res
- [ "$res" = 1 ] && add_ddns || set_ddns
+ while true; do
+ line_break
+ read -r -p "$DDNS_INPUT_DOMAIN> " str
+ [ -z "$str" ] && domain="$domain" || domain="$str"
+ echo ""
+ read -r -p "$DDNS_INPUT_USER> " str
+ [ -z "$str" ] && username="$username" || username="$str"
+ echo ""
+ read -r -p "$DDNS_INPUT_PASS> " str
+ [ -z "$str" ] && password="$password" || password="$str"
+ echo ""
+ read -r -p "$DDNS_INPUT_CHECK_INTERVAL> " check_interval
+ [ -z "$check_interval" ] || [ "$check_interval" -lt 1 -o "$check_interval" -gt 1440 ] && check_interval=10
+ echo ""
+ read -r -p "$DDNS_INPUT_FORCE_INTERVAL> " force_interval
+ [ -z "$force_interval" ] || [ "$force_interval" -lt 1 -o "$force_interval" -gt 240 ] && force_interval=24
+
+ comp_box "$DDNS_CONFIRM_INFO" \
+ "" \
+ "$DDNS_FIELD_SERVICE \033[32m$service\033[0m" \
+ "$DDNS_FIELD_DOMAIN \033[32m$domain\033[0m" \
+ "$DDNS_FIELD_USER \033[32m$username\033[0m" \
+ "$DDNS_FIELD_INTERVAL \033[32m$check_interval\033[0m"
+ btm_box "$DDNS_CONFIRM_ADD"
+ btm_box "1) $DDNS_YES" \
+ "0) $DDNS_REINPUT"
+ read -r -p "$COMMON_INPUT> " res
+ if [ "$res" = 1 ]; then
+ add_ddns
+ break
+ fi
+ done
}
+
set_ddns_service() {
- services_dir=/etc/ddns/"$serv"
- [ -s "$services_dir" ] || services_dir=/etc/ddns/services
- [ -s "$services_dir" ] || services_dir=/usr/share/ddns/list
- [ -s "$services_dir" ] || {
- echo -e "\033[33m未找到DDNS列表文件,尝试在线获取……\033[0m"
- ddns service update >/dev/null || echo -e "\033[31m下载失败,请重试!\033[0m"
- }
- echo -----------------------------------------------
- echo -e "\033[32m请选择服务提供商\033[0m"
- cat "$services_dir" | grep -vE '^#|^[[:space:]]*$' | awk '{print " "NR" " $1}'
- nr=$(cat "$services_dir" | grep -vE '^#|^[[:space:]]*$' | wc -l)
- read -p "请输入对应数字 > " num
- if [ -z "$num" ]; then
- i=
- elif [ "$num" -gt 0 -a "$num" -lt $nr ]; then
- service_name=$(cat "$services_dir" | grep -vE '^#|^[[:space:]]*$' | awk '{print $1}' | sed -n "$num"p | sed 's/"//g')
- service=$(echo $service_name | sed 's/\./_/g')
- set_ddns
- else
- echo "输入错误,请重新输入!"
- sleep 1
- set_ddns_service
- fi
+ while true; do
+ services_dir=/etc/ddns/"$serv"
+ [ -s "$services_dir" ] || services_dir=/etc/ddns/services
+ [ -s "$services_dir" ] || services_dir=/usr/share/ddns/list
+ [ -s "$services_dir" ] || {
+ msg_alert "\033[33m$DDNS_LIST_NOT_FOUND\033[0m"
+ ddns service update >/dev/null || msg_alert "\033[31m$DDNS_DOWNLOAD_FAILED\033[0m"
+ }
+ comp_box "\033[32m$DDNS_SELECT_PROVIDER\033[0m"
+
+ list=$(awk '/^#/ || !NF {next} {print $1}' "$services_dir")
+ list_box "$list"
+
+ nr=$(echo "$list" | wc -l)
+ common_back
+ read -r -p "$COMMON_INPUT> " num
+ if [ -z "$num" ] || [ "$num" = 0 ]; then
+ i=
+ break
+ elif [ "$num" -gt 0 ] && [ "$num" -lt "$nr" ]; then
+ service_name=$(echo "$list" | sed -n "$num"p | sed 's/"//g')
+ service=$(echo "$service_name" | sed 's/\./_/g')
+ set_ddns
+ break
+ else
+ msg_alert "\033[33m$DDNS_INPUT_ERROR\033[0m"
+ fi
+ done
}
+
set_ddns_type() {
- echo -----------------------------------------------
- echo -e "\033[32m请选择网络模式\033[0m"
- echo -e " 1 \033[36mIPV4\033[0m"
- echo -e " 2 \033[36mIPV6\033[0m"
- read -p "请输入对应数字 > " num
- if [ -z "$num" ]; then
- i=
- elif [ "$num" = 1 ]; then
- use_ipv6=0
- serv=services
- set_ddns_service
- elif [ "$num" = 2 ]; then
- use_ipv6=1
- serv=services_ipv6
- set_ddns_service
- else
- echo "输入错误,请重新输入!"
- sleep 1
- set_ddns_type
- fi
+ while true; do
+ comp_box "\033[32m$DDNS_SELECT_NETMODE\033[0m"
+ btm_box "1) \033[36m$DDNS_IPV4\033[0m" \
+ "2) \033[36m$DDNS_IPV6\033[0m" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " 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$DDNS_INPUT_ERROR\033[0m"
+ ;;
+ esac
+ done
}
+
rev_ddns_service() {
- enabled=$(uci get ddns."$service".enabled)
- [ "$enabled" = 1 ] && enabled_b="停用" || enabled_b="启用"
- echo -----------------------------------------------
- echo -e " 1 \033[32m立即更新\033[0m"
- echo -e " 2 编辑当前服务\033[0m"
- echo -e " 3 $enabled_b当前服务"
- echo -e " 4 移除当前服务"
- echo -e " 5 查看运行日志"
- echo -e " 0 返回上级菜单"
- echo -----------------------------------------------
- read -p "请输入对应数字 > " num
- if [ -z "$num" -o "$num" = 0 ]; then
- i=
- elif [ "$num" = 1 ]; then
- /usr/lib/ddns/dynamic_dns_updater.sh -S $service start >/dev/null 2>&1 &
- sleep 3
- elif [ "$num" = 2 ]; then
- 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
- elif [ "$num" = 3 ]; then
- [ "$enabled" = 1 ] && uci set ddns."$service".enabled='0' || uci set ddns."$service".enabled='1' && sleep 3
- uci commit ddns."$service"
- elif [ "$num" = 4 ]; then
- uci delete ddns."$service"
- uci commit ddns."$service"
- elif [ "$num" = 5 ]; then
- echo -----------------------------------------------
- cat /var/log/ddns/"$service".log 2>/dev/null
- sleep 1
- fi
+ while true; do
+ enabled=$(uci get ddns."$service".enabled)
+ [ "$enabled" = 1 ] && enabled_b="$DDNS_DISABLE" || enabled_b="$DDNS_ENABLE"
+ comp_box "1) \033[32m$DDNS_UPDATE_NOW\033[0m" \
+ "2) $DDNS_EDIT_CURRENT" \
+ "3) $enabled_b$DDNS_CURRENT_SERVICE" \
+ "4) $DDNS_REMOVE_CURRENT" \
+ "5) $DDNS_VIEW_LOG" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " 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
+ echo "==========================================================="
+ cat /var/log/ddns/"$service".log 2>/dev/null
+ echo "==========================================================="
+ break
+ ;;
+ *)
+ msg_alert "\033[33m$DDNS_INPUT_ERROR\033[0m"
+ ;;
+ esac
+ done
}
+
load_ddns() {
- ddns_dir=/etc/config/ddns
- tmp_dir="$TMPDIR"/ddns
- [ ! -f "$ddns_dir" ] && {
- echo -e "\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"
- echo -----------------------------------------------
- echo -e "列表 域名 启用 IP地址"
- echo -----------------------------------------------
- [ -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 "'\"")
- echo -e " $nr $domain $enabled $local_ip"
- done
- echo -e " $((nr + 1)) 添加DDNS服务"
- echo -e " 0 退出"
- echo -----------------------------------------------
- read -p "请输入对应序号 > " num
- if [ -z "$num" -o "$num" = 0 ]; then
- i=
- elif [ "$num" -gt $nr ]; then
- set_ddns_type
- load_ddns
- elif [ "$num" -gt 0 -a "$num" -le $nr ]; then
- service=$(cat $tmp_dir | sed -n "$num"p)
- rev_ddns_service
- load_ddns
- else
- echo "请输入正确数字!" && load_ddns
- fi
- rm -rf "$tmp_dir"
+ while true; do
+ ddns_dir=/etc/config/ddns
+ tmp_dir="$TMPDIR"/ddns
+ [ ! -f "$ddns_dir" ] && {
+ btm_box "\033[31m$DDNS_NOT_SUPPORTED\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 "$DDNS_LIST_HEADER"
+ 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_ADD_SERVICE"
+ content_line "0) $DDNS_EXIT"
+ separator_line "="
+ read -r -p "$DDNS_INPUT_INDEX> " 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$DDNS_INPUT_NUM_ERROR\033[0m"
+ fi
+ done
}
-
-
diff --git a/scripts/menus/dns.sh b/scripts/menus/dns.sh
index 1562079e..b960d2f3 100644
--- a/scripts/menus/dns.sh
+++ b/scripts/menus/dns.sh
@@ -4,231 +4,338 @@
[ -n "$__IS_MODULE_DNS_LOADED" ] && return
__IS_MODULE_DNS_LOADED=1
-set_dns_mod() { #DNS模式设置
- [ -z "$hosts_opt" ] && hosts_opt=ON
- [ -z "$dns_protect" ] && dns_protect=ON
- [ -z "$ecs_subnet" ] && ecs_subnet=OFF
- echo "-----------------------------------------------"
- echo -e "当前DNS运行模式为:\033[47;30m $dns_mod \033[0m"
- echo -e "\033[33m切换模式后需要手动重启服务以生效!\033[0m"
- echo "-----------------------------------------------"
- echo -e " 1 MIX模式: \033[32mCN域名realip其他fake-ip分流\033[0m"
- echo -e " 2 Route模式:\033[32mCN域名realip其他dns2proxy分流\033[0m"
- echo -e " 3 Redir模式:\033[33m不安全,需搭配第三方DNS服务使用\033[0m"
- echo "-----------------------------------------------"
- echo -e " 4 DNS防泄漏: \033[36m$dns_protect\033[0m ———启用时少量网站可能连接卡顿"
- echo -e " 5 Hosts优化: \033[36m$hosts_opt\033[0m ———调用本机hosts并劫持NTP服务"
- echo -e " 6 ECS优化: \033[36m$ecs_subnet\033[0m ———解决CDN下载浪费流量等问题"
- echo -e " 7 DNS劫持端口:\033[36m$dns_redir_port\033[0m ———用于兼容第三方DNS服务"
- [ "$dns_mod" = "mix" ] &&
- echo -e " 8 管理MIX模式\033[33mFake-ip过滤列表\033[0m"
- echo -e " 9 修改\033[36mDNS服务器\033[0m"
- echo "-----------------------------------------------"
- echo " 0 返回上级菜单"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0) ;;
- 1)
- if echo "$crashcore" | grep -q 'singbox' || [ "$crashcore" = meta ]; then
- dns_mod=mix
- setconfig dns_mod $dns_mod
- echo "-----------------------------------------------"
- echo -e "\033[36m已设为 $dns_mod 模式!!\033[0m"
- else
- echo -e "\033[31m当前内核不支持的功能!!!\033[0m"
- sleep 1
- fi
- set_dns_mod
- ;;
- 2)
- if echo "$crashcore" | grep -q 'singbox' || [ "$crashcore" = meta ]; then
- dns_mod=route
- setconfig dns_mod $dns_mod
- echo "-----------------------------------------------"
- echo -e "\033[36m已设为 $dns_mod 模式!!\033[0m"
- else
- echo -e "\033[31m当前内核不支持的功能!!!\033[0m"
- sleep 1
- fi
- set_dns_mod
- ;;
- 3)
- dns_mod=redir_host
- setconfig dns_mod $dns_mod
- echo "-----------------------------------------------"
- echo -e "\033[36m已设为 $dns_mod 模式!!\033[0m"
- set_dns_mod
- ;;
- 4)
- [ "$dns_protect" = "ON" ] && dns_protect=OFF || dns_protect=ON
- setconfig dns_protect $dns_protect
- set_dns_mod
- ;;
- 5)
- [ "$hosts_opt" = "ON" ] && hosts_opt=OFF || hosts_opt=ON
- setconfig hosts_opt $hosts_opt
- set_dns_mod
- ;;
- 6)
- [ "$ecs_subnet" = "ON" ] && ecs_subnet=OFF || ecs_subnet=ON
- setconfig ecs_subnet "$ecs_subnet"
- set_dns_mod
- ;;
- 7)
- echo "-----------------------------------------------"
- echo -e "\033[31m仅限搭配第三方DNS服务(AdGuard、SmartDNS……)使用!\033[0m"
- echo -e "\033[33m设置为第三方DNS服务的监听端口即可修改防火墙劫持!\n建议在第三方DNS服务中将上游DNS指向【localhost:$dns_port】\033[0m"
- echo "-----------------------------------------------"
- read -p "请输入第三方DNS服务的监听端口(0重置端口) > " num
- if [ "$num" = 0 ];then
- dns_redir_port="$dns_port"
- setconfig dns_redir_port
- elif [ "$num" -lt 65535 -a "$num" -ge 1 ];then
- if ckcmd netstat;then
- port_test=$(netstat -ntul | grep -E ":$num[[:space:]]")
- else
- port_test=0
- fi
- if [ -n "$port_test" ];then
- dns_redir_port="$num"
- setconfig dns_redir_port "$dns_redir_port"
- else
- echo -e "\033[33m此端口未检测到已运行的DNS服务!\033[0m"
- fi
- else
- errornum
- fi
- sleep 1
- set_dns_mod
- ;;
- 8)
- echo "-----------------------------------------------"
- fake_ip_filter
- set_dns_mod
- ;;
- 9)
- set_dns_adv
- set_dns_mod
- ;;
- *)
- errornum
- ;;
- esac
+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
+ comp_box "$DNS_CURRENT_MODE\033[47;30m $dns_mod \033[0m" \
+ "\033[33m$DNS_RESTART_NOTICE\033[0m"
+ content_line "1) $DNS_SET_TO MIX$COMMON_MOD:\t\033[32m$DNS_MODE_MIX_DESC\033[0m"
+ content_line "2) $DNS_SET_TO Route$COMMON_MOD:\t\033[32m$DNS_MODE_ROUTE_DESC\033[0m"
+ content_line "3) $DNS_SET_TO 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)
+ if echo "$crashcore" | grep -q 'singbox' || [ "$crashcore" = meta ]; then
+ [ "$num" = 1 ] && dns_mod=mix || dns_mod=route
+ setconfig dns_mod "$dns_mod"
+ msg_alert "\033[36m$DNS_SET_OK:$dns_mod\033[0m"
+ else
+ msg_alert "\033[31m$DNS_CORE_UNSUPPORTED\033[0m"
+ fi
+ ;;
+ 3)
+ dns_mod=redir_host
+ setconfig dns_mod "$dns_mod"
+ msg_alert "\033[36m$DNS_SET_OK:$dns_mod\033[0m"
+ ;;
+ 4)
+ if [ "$dns_protect" = ON ]; then
+ dns_protect=OFF
+ else
+ dns_protect=ON
+ fi
+ setconfig dns_protect "$dns_protect"
+ common_success
+ ;;
+ 5)
+ if [ "$hosts_opt" = ON ]; then
+ hosts_opt=OFF
+ else
+ hosts_opt=ON
+ fi
+ setconfig hosts_opt "$hosts_opt"
+ common_success
+ ;;
+ 6)
+ if [ "$ecs_subnet" = ON ]; then
+ ecs_subnet=OFF
+ else
+ ecs_subnet=ON
+ fi
+ setconfig ecs_subnet "$ecs_subnet"
+ common_success
+ ;;
+ 7)
+ while true; do
+ comp_box "\033[31m$DNS_REDIR_WARN\033[0m" \
+ "\033[33m$DNS_REDIR_HINT 127.0.0.1:$dns_port\033[0m" \
+ "" \
+ "\033[36m$DNS_INPUT_REDIR_PORT\033[0m" \
+ "$DNS_INPUT_REDIR_RESET" \
+ "$DNS_INPUT_REDIR_BACK"
+ read -r -p "$DNS_INPUT> " num
+ case "$num" in
+ 0)
+ break
+ ;;
+ r)
+ dns_redir_port="$dns_port"
+ setconfig dns_redir_port
+ common_success
+ break
+ ;;
+ *)
+ if [ "$num" -ge 1 ] && [ "$num" -lt 65535 ]; then
+ if ckcmd netstat && netstat -ntul | grep -q ":$num "; then
+ dns_redir_port="$num"
+ setconfig dns_redir_port "$dns_redir_port"
+ common_success
+ break
+ else
+ msg_alert "\033[33m$DNS_REDIR_NO_SERVICE\033[0m"
+ fi
+ else
+ errornum
+ fi
+ ;;
+ esac
+ done
+ ;;
+ 8)
+ fake_ip_filter
+ ;;
+ 9)
+ set_dns_adv
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
}
+
fake_ip_filter() {
- echo -e "\033[32m用于解决Fake-ip模式下部分地址或应用无法连接的问题\033[0m"
- echo -e "\033[31m脚本已经内置了大量地址,你只需要添加出现问题的地址!\033[0m"
- echo -e "\033[36m示例:a.b.com"
- echo -e "示例:*.b.com"
- echo -e "示例:*.*.b.com\033[0m"
- echo "-----------------------------------------------"
- if [ -s ${CRASHDIR}/configs/fake_ip_filter ]; then
- echo -e "\033[33m已添加Fake-ip过滤地址:\033[0m"
- cat ${CRASHDIR}/configs/fake_ip_filter | awk '{print NR" "$1}'
- else
- echo -e "\033[33m你还未添加Fake-ip过滤地址\033[0m"
- fi
- echo "-----------------------------------------------"
- echo -e "\033[32m输入数字直接移除对应地址,输入地址直接添加!\033[0m"
- read -p "请输入数字或地址 > " input
- case "$input" in
- 0) ;;
- '') ;;
- *)
- if [ $input -ge 1 ] 2>/dev/null; then
- sed -i "${input}d" ${CRASHDIR}/configs/fake_ip_filter 2>/dev/null
- echo -e "\033[32m移除成功!\033[0m"
+ while true; do
+ comp_box "\033[32m$DNS_FAKEIP_DESC\033[0m" \
+ "\033[31m$DNS_FAKEIP_TIP\033[0m" \
+ "\033[36m$DNS_FAKEIP_EXAMPLE\033[0m"
+ 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
- echo -e "你输入的地址是:\033[32m$input\033[0m"
- read -p "确认添加?(1/0) > " res
- [ "$res" = 1 ] && echo $input >>${CRASHDIR}/configs/fake_ip_filter
+ content_line "\033[33m$DNS_FAKEIP_EMPTY\033[0m"
fi
- sleep 1
- fake_ip_filter
- ;;
- esac
+ btm_box "" \
+ "0) $COMMON_BACK"
+ read -r -p "$DNS_FAKEIP_EDIT> " input
+ case "$input" in
+ "" | 0)
+ break
+ ;;
+ *)
+ if [ "$input" -ge 1 ] 2>/dev/null; then
+ if sed -i "${input}d" "$CRASHDIR/configs/fake_ip_filter"; then
+ msg_alert "\033[32m$DNS_REMOVE_OK\033[0m"
+ else
+ msg_alert "\033[31m$DNS_REMOVE_FAIL\033[0m"
+ fi
+ else
+ comp_box "$DNS_CONFIRM_ADD\033[32m$input\033[0m"
+ btm_box "1) $DNS_CONFIRM_OK" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT>" res
+ if [ "$res" = 1 ]; then
+ if echo "$input" >>"$CRASHDIR/configs/fake_ip_filter"; then
+ msg_alert "\033[32m$DNS_ADD_OK\033[0m"
+ else
+ msg_alert "\033[31m$DNS_ADD_FAIL\033[0m"
+ fi
+ else
+ break
+ fi
+ fi
+ ;;
+ esac
+ done
}
-set_dns_adv() { #DNS详细设置
- echo "-----------------------------------------------"
- echo -e "当前基础DNS:\033[32m$dns_nameserver\033[0m"
- echo -e "PROXY-DNS:\033[36m$dns_fallback\033[0m"
- echo -e "解析DNS:\033[33m$dns_resolver\033[0m"
- echo -e "多个DNS地址请用\033[30;47m“|”\033[0m或者\033[30;47m“, ”\033[0m分隔输入"
- echo -e "\033[33m必须拥有本地根证书文件才能使用dot/doh类型的加密dns\033[0m"
- echo -e "\033[31m注意singbox内核只有首个dns会被加载!\033[0m"
- echo "-----------------------------------------------"
- echo -e " 1 修改\033[32m基础DNS\033[0m"
- echo -e " 2 修改\033[36mPROXY-DNS\033[0m(该DNS查询会经过节点)"
- echo -e " 3 修改\033[33m解析DNS\033[0m(必须是IP,用于解析其他DNS)"
- echo -e " 4 一键配置\033[32m加密DNS\033[0m"
- echo -e " 9 \033[33m重置\033[0m默认DNS配置"
- echo -e " 0 返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0) ;;
- 1)
- read -p "请输入新的DNS > " dns_nameserver
- dns_nameserver=$(echo $dns_nameserver | sed 's#|#\,\ #g')
- if [ -n "$dns_nameserver" ]; then
- setconfig dns_nameserver "'$dns_nameserver'"
- echo -e "\033[32m设置成功!!!\033[0m"
- fi
- sleep 1
- set_dns_adv
- ;;
- 2)
- read -p "请输入新的DNS > " dns_fallback
- dns_fallback=$(echo $dns_fallback | sed 's/|/\,\ /g')
- if [ -n "$dns_fallback" ]; then
- setconfig dns_fallback "'$dns_fallback'"
- echo -e "\033[32m设置成功!!!\033[0m"
- fi
- sleep 1
- set_dns_adv
- ;;
- 3)
- read -p "请输入新的DNS > " text
- if echo "$text" | grep -qE '://.*::'; then
- echo -e "\033[31m此选项暂不支持ipv6加密DNS!!!\033[0m"
- elif [ -n "$text" ]; then
- dns_resolver=$(echo $text | sed 's/|/\,\ /g')
- setconfig dns_resolver "'$dns_resolver'"
- echo -e "\033[32m设置成功!!!\033[0m"
- fi
- sleep 1
- set_dns_adv
- ;;
- 4)
- echo "-----------------------------------------------"
- openssldir="$(openssl version -d 2>&1 | awk -F '"' '{print $2}')"
- if [ -s "$openssldir/certs/ca-certificates.crt" ] || [ -s "/etc/ssl/certs/ca-certificates.crt" ] ||
- 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'"
- echo -e "\033[32m已设置加密DNS,如出现DNS解析问题,请尝试重置DNS配置!\033[0m"
- else
- echo -e "\033[31m找不到根证书文件,无法启用加密DNS,Linux系统请自行搜索安装OpenSSL的方式!\033[0m"
- fi
- sleep 1
- set_dns_adv
- ;;
- 9)
- setconfig dns_nameserver
- setconfig dns_fallback
- setconfig dns_resolver
- . "$CRASHDIR"/libs/get_config.sh
- echo -e "\033[33mDNS配置已重置!!!\033[0m"
- sleep 1
- set_dns_adv
- ;;
- *)
- errornum
- sleep 1
- ;;
- esac
+
+# DNS详细设置
+set_dns_adv() {
+ while true; do
+ comp_box "\033[31m$DNS_ADV_SINGBOX_LIMIT\033[0m" \
+ "$DNS_ADV_SPLIT" \
+ "\033[33m$DNS_ADV_CERT\033[0m" \
+ "" \
+ "DIRECT-DNS:" \
+ "\033[32m$dns_nameserver\033[0m" \
+ "" \
+ "PROXY-DNS:" \
+ "\033[36m$dns_fallback\033[0m" \
+ "" \
+ "RESOLVER-DNS:" \
+ "\033[33m$dns_resolver\033[0m" \
+ "" \
+ "PROXY-SERVER-DNS:" \
+ "\033[33m$dns_proxy_server\033[0m" \
+ ""
+ btm_box "1) $DNS_ADV_EDIT_DIRECT" \
+ "2) $DNS_ADV_EDIT_PROXY" \
+ "3) $DNS_ADV_EDIT_RESOLVER" \
+ "4) $DNS_ADV_EDIT_PROXY_SERVER" \
+ "5) \033[32m$DNS_ADV_AUTO_ENCRYPT\033[0m" \
+ "9) \033[33m$DNS_ADV_RESET\033[0m" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ comp_box "$DNS_NOW\033[32m$dns_nameserver\033[0m"
+ btm_box "\033[36m$DNS_INPUT_NEW\033[0m" \
+ "$DNS_INPUT_RESET" \
+ "$DNS_INPUT_REDIR_BACK"
+ read -r -p "$DNS_INPUT> " res
+ case "$res" in
+ 0)
+ continue
+ ;;
+ r)
+ dns_nameserver="127.0.0.1"
+ setconfig dns_nameserver "'$dns_nameserver'"
+ common_success
+ ;;
+ *)
+ dns_nameserver=$(echo "$res" | sed 's#|#,\ #g')
+ if [ -n "$dns_nameserver" ]; then
+ setconfig dns_nameserver "'$dns_nameserver'"
+ common_success
+ else
+ common_failed
+ fi
+ ;;
+ esac
+ ;;
+ 2)
+ comp_box "$DNS_NOW\033[32m$dns_fallback\033[0m"
+ btm_box "\033[36m$DNS_INPUT_NEW\033[0m" \
+ "$DNS_INPUT_RESET" \
+ "$DNS_INPUT_REDIR_BACK"
+ read -r -p "$DNS_INPUT> " res
+ case "$res" in
+ 0)
+ continue
+ ;;
+ r)
+ dns_fallback="1.1.1.1, 8.8.8.8"
+ setconfig dns_fallback "'$dns_fallback'"
+ common_success
+ ;;
+ *)
+ dns_fallback=$(echo "$res" | sed 's#|#,\ #g')
+ if [ -n "$dns_fallback" ]; then
+ setconfig dns_fallback "'$dns_fallback'"
+ common_success
+ else
+ common_failed
+ fi
+ ;;
+ esac
+ ;;
+ 3)
+ comp_box "$DNS_NOW\033[32m$dns_resolver\033[0m"
+ btm_box "\033[36m$DNS_INPUT_NEW\033[0m" \
+ "$DNS_INPUT_RESET" \
+ "$DNS_INPUT_REDIR_BACK"
+ separator_line "="
+ read -r -p "$DNS_INPUT> " res
+ case "$res" in
+ 0)
+ continue
+ ;;
+ "r")
+ dns_resolver="223.5.5.5, 2400:3200::1"
+ setconfig dns_resolver "'$dns_resolver'"
+ common_success
+ ;;
+ *)
+ if echo "$res" | grep -qE '://.*::'; then
+ msg_alert "\033[31m$DNS_IPV6_NOT_SUPPORT\033[0m"
+ else
+ dns_resolver=$(echo "$res" | sed 's#|#,\ #g')
+ setconfig dns_resolver "'$dns_resolver'"
+ msg_alert "\033[32m$COMMON_SUCCESS\033[0m"
+ fi
+ ;;
+ esac
+ ;;
+ 4)
+ comp_box "$DNS_NOW\033[32m$dns_proxy_server\033[0m"
+ btm_box "\033[36m$DNS_INPUT_NEW\033[0m" \
+ "$DNS_INPUT_RESET" \
+ "$DNS_INPUT_REDIR_BACK"
+ separator_line "="
+ read -r -p "$DNS_INPUT> " res
+ case "$res" in
+ 0)
+ continue
+ ;;
+ "r")
+ dns_proxy_server="$dns_resolver"
+ setconfig dns_proxy_server "'$dns_proxy_server'"
+ common_success
+ ;;
+ *)
+ if echo "$res" | grep -qE '://.*::'; then
+ msg_alert "\033[31m$DNS_IPV6_NOT_SUPPORT\033[0m"
+ else
+ dns_proxy_server=$(echo "$res" | sed 's#|#,\ #g')
+ setconfig dns_proxy_server "'$dns_proxy_server'"
+ msg_alert "\033[32m$COMMON_SUCCESS\033[0m"
+ fi
+ ;;
+ esac
+ ;;
+ 5)
+ 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"
+ common_success
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
}
diff --git a/scripts/menus/fw_filter.sh b/scripts/menus/fw_filter.sh
new file mode 100644
index 00000000..afadc578
--- /dev/null
+++ b/scripts/menus/fw_filter.sh
@@ -0,0 +1,509 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+[ -n "$__IS_MODULE_FW_FILTER_LOADED" ] && return
+__IS_MODULE_FW_FILTER_LOADED=1
+load_lang fw_filter
+
+# 流量过滤
+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_filter_info=OFF || mac_filter_info=ON
+ comp_box "${FWF_ITEM_1_PREFIX}\033[36m$common_ports\033[0m\t${FWF_ITEM_1_SUFFIX}" \
+ "${FWF_ITEM_2_PREFIX}\033[36m$mac_filter_info\033[0m\t${FWF_ITEM_2_SUFFIX}" \
+ "${FWF_ITEM_3_PREFIX}\033[36m$quic_rj\033[0m\t${FWF_ITEM_3_SUFFIX}" \
+ "${FWF_ITEM_4_PREFIX}\033[36m$cn_ip_route\033[0m\t${FWF_ITEM_4_SUFFIX}" \
+ "$FWF_ITEM_5" \
+ "$FWF_ITEM_6" \
+ "" \
+ "$FWF_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ if [ -n "$(pidof CrashCore)" ] && [ "$firewall_mod" = 'iptables' ]; then
+ comp_box "$FWF_SWITCH_STOP"
+ btm_box "$FWF_YES" \
+ "$FWF_NO_BACK"
+ 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$FWF_QUIC_OFF\033[0m"
+ else
+ quic_rj=OFF
+ msg_alert "\033[33m$FWF_QUIC_ON\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$FWF_CNIP_ON\033[0m" \
+ "\033[31m$FWF_CNIP_WARN\033[0m"
+ else
+ cn_ip_route=OFF
+ msg_alert "\033[33m$FWF_CNIP_OFF\033[0m"
+ fi
+ setconfig cn_ip_route $cn_ip_route
+ else
+ msg_alert "\033[31m$FWF_NO_IPSET\033[0m"
+ fi
+ ;;
+ 5)
+ set_cust_host_ipv4
+ ;;
+ 6)
+ set_reserve_ipv4
+ ;;
+ *)
+ 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$FWF_COMMON_NOTE\033[0m$FWF_MIX_NOTE"
+ if [ -n "$common_ports" ]; then
+ content_line ""
+ content_line "$FWF_ALLOWED_PORTS\033[36m$multiport\033[0m"
+ fi
+ separator_line "="
+ btm_box "${FWF_PORT_MENU_1_PREFIX}\033[36m$common_ports\033[0m${FWF_PORT_MENU_1_SUFFIX}" \
+ "$FWF_PORT_MENU_2" \
+ "$FWF_PORT_MENU_3" \
+ "$FWF_PORT_MENU_4" \
+ "$FWF_PORT_MENU_5" \
+ "" \
+ "$FWF_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$FWF_MAX_PORT\033[0m"
+ else
+ comp_box "$FWF_ALLOWED_PORTS\033[36m$multiport\033[0m"
+ btm_box "\033[36m$FWF_INPUT_ADD_HINT\033[0m\n$FWF_INPUT_ADD_HINT2" \
+ "$FWF_OR_BACK"
+ read -r -p "$FWF_INPUT_PORT" port
+ if [ "$port" = 0 ]; then
+ break
+ elif echo ",$multiport," | grep -q ",$port,"; then
+ msg_alert "\033[31m$FWF_ERR_DUP\033[0m"
+ elif [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
+ msg_alert "\033[31m$FWF_ERR_RANGE\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 "$FWF_ALLOWED_PORTS\033[36m$multiport\033[0m"
+ btm_box "\033[36m$FWF_INPUT_REMOVE_HINT\033[0m\n$FWF_INPUT_ADD_HINT2" \
+ "$FWF_OR_BACK"
+ read -r -p "$FWF_INPUT_PORT" 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$FWF_ERR_RANGE\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$FWF_ERR_DUP\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 "$FWF_CUST_HOST_TITLE\033[32m$host_ipv4\033[0m" \
+ "$FWF_CUST_HOST_TITLE2\033[36m$cust_host_ipv4\033[0m"
+ btm_box "$FWF_CUST_HOST_MENU_1" \
+ "$FWF_CUST_HOST_MENU_2 \033[36m$replace_default_host_ipv4\033[0m" \
+ "" \
+ "$FWF_BACK"
+ read -r -p "$FWF_CUST_HOST_HINT" 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 echo "$text" | grep -Eq '^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]{1,2}' && [ -z "$(echo $cust_host_ipv4 | grep "$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$FWF_NET_ERR\033[0m"
+ fi
+ ;;
+ esac
+ done
+}
+
+set_reserve_ipv4() {
+ 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$FWF_RESERVE_NOTE\033[0m" \
+ "" \
+ "$FWF_RESERVE_NOW" \
+ "\033[36m$reserve_ipv4\033[0m"
+ btm_box "\033[36m$FWF_RESERVE_INPUT_HINT\033[0m" \
+ "$FWF_RESERVE_INPUT_HINT2" \
+ "$FWF_RESERVE_INPUT_HINT3"
+ read -r -p "$FWF_RESERVE_PROMPT" text
+ case "$text" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ unset reserve_ipv4
+ if setconfig reserve_ipv4; then
+ msg_alert "\033[32m$COMMON_SUCCESS\033[0m"
+ else
+ msg_alert "\033[31m$COMMON_FAILED\033[0m"
+ fi
+ ;;
+ *)
+ if 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$FWF_RESERVE_SET$reserve_ipv4\033[0m"
+ else
+ msg_alert "\033[31m$COMMON_FAILED\033[0m"
+ fi
+ else
+ msg_alert "\033[31m$FWF_RESERVE_ERR\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="$FWF_LAN_NO_DEVICE"
+ }
+ add_mac() {
+ while true; do
+ comp_box "$FWF_MAC_HINT"
+ content_line "$FWF_MAC_EXISTED"
+ content_line ""
+ if [ -s "$CRASHDIR/configs/mac" ]; then
+ while IFS= read -r line; do
+ content_line "$line"
+ done <"$CRASHDIR/configs/mac"
+ else
+ content_line "$FWF_NONE_MAC"
+ fi
+ separator_line "="
+ content_line "$FWF_MAC_HEADER"
+ if [ -s "$dhcpdir" ]; then
+ awk '{print NR") "$3,$2,$4}' "$dhcpdir" |
+ while IFS= read -r line; do
+ content_line "$line"
+ done
+ else
+ content_line "$FWF_MAC_NONE"
+ fi
+ btm_box "" \
+ "$FWF_BACK"
+ read -r -p "$FWF_MAC_INPUT_HINT" 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$FWF_MAC_DUP\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$FWF_MAC_DUP\033[0m"
+ fi
+ else
+ msg_alert "\033[31m$FWF_RESERVE_ERR\033[0m"
+ fi
+ done
+ }
+
+ add_ip() {
+ while true; do
+ comp_box "$FWF_IP_HINT" \
+ "$FWF_IP_HINT2"
+ content_line "$FWF_IP_EXISTED"
+ 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 "$FWF_NONE_IP"
+ fi
+
+ separator_line "="
+ content_line "$FWF_IP_HEADER"
+ if [ -s "$dhcpdir" ]; then
+ awk '{print NR") "$3, $4}' "$dhcpdir" |
+ while IFS= read -r line; do
+ content_line "$line"
+ done
+ else
+ content_line "$FWF_MAC_NONE"
+ fi
+ btm_box "" \
+ "$FWF_BACK"
+ read -r -p "$FWF_IP_INPUT_HINT" 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$FWF_IP_DUP\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$FWF_IP_DUP\033[0m"
+ fi
+ else
+ msg_alert "\033[31m$FWF_RESERVE_ERR\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$FWF_REMOVE_NONE\033[0m"
+ break
+ else
+ comp_box "$FWF_REMOVE_TITLE"
+ content_line "$FWF_REMOVE_HEADER"
+ 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
+ btm_box "" \
+ "$FWF_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$FWF_REMOVE_OK\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$FWF_REMOVE_OK\033[0m"
+ else
+ msg_alert "\033[31m$FWF_RESERVE_ERR\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
+ macfilter_type_show="$FWF_BLACK_LIST"
+ fw_filter_lan_over="$FWF_WHITE_LIST"
+ fw_filter_lan_desc="$FWF_FILTER_BLACK_DESC"
+ else
+ macfilter_type_show="$FWF_WHITE_LIST"
+ fw_filter_lan_over="$FWF_BLACK_LIST"
+ fw_filter_lan_desc="$FWF_FILTER_WHITE_DESC"
+ fi
+
+ comp_box "\033[30;47m$FWF_FILTER_MENU_TITLE\033[0m" \
+ "" \
+ "$FWF_FILTER_MODE\033[33m$macfilter_type_show$FWF_FILTER_MODE_SUFFIX\033[0m" \
+ "\033[36m$fw_filter_lan_desc\033[0m"
+ if [ -n "$(cat "$CRASHDIR"/configs/mac)" ]; then
+ content_line "$FWF_FILTER_EXISTED"
+ content_line ""
+ content_line "$FWF_FILTER_HEADER"
+ 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
+ btm_box "${FWF_FILTER_SWITCH_PREFIX}\033[33m$fw_filter_lan_over\033[0m${FWF_FILTER_SWITCH_SUFFIX}" \
+ "$FWF_FILTER_ADD_MAC" \
+ "$FWF_FILTER_ADD_IP" \
+ "$FWF_FILTER_REMOVE" \
+ "$FWF_FILTER_CLEAR" \
+ "" \
+ "$FWF_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ if [ "$macfilter_type" = '黑名单' ]; then
+ macfilter_type='白名单'
+ else
+ macfilter_type='黑名单'
+ fi
+ if setconfig macfilter_type "$macfilter_type"; then
+ msg_alert "\033[32m$FWF_SWITCH_OK\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$FWF_LIST_CLEARED\033[0m"
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
+}
diff --git a/scripts/menus/override.sh b/scripts/menus/override.sh
new file mode 100644
index 00000000..a4e2275c
--- /dev/null
+++ b/scripts/menus/override.sh
@@ -0,0 +1,549 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+[ -n "$__IS_MODULE_OVERRIDE" ] && return
+__IS_MODULE_OVERRIDE=1
+YAMLSDIR="$CRASHDIR"/yamls
+JSONSDIR="$CRASHDIR"/jsons
+load_lang override
+
+# 配置文件覆写
+override() {
+ while true; do
+ [ -z "$rule_link" ] && rule_link=1
+ [ -z "$server_link" ] && server_link=1
+ comp_box "\033[30;47m $OVR_TITLE\033[0m"
+ content_line "$OVR_MENU_2"
+ echo "$crashcore" | grep -q 'singbox' || {
+ content_line "$OVR_MENU_3"
+ content_line "$OVR_MENU_4"
+ }
+ content_line "$OVR_MENU_5"
+ [ "$disoverride" != 1 ] && content_line "$OVR_MENU_9"
+ content_line ""
+ content_line "$OVR_BACK"
+ separator_line "="
+ read -r -p "$OVR_INPUT_NUM" num
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ 2)
+ setrules
+ ;;
+ 3)
+ setproxies
+ ;;
+ 4)
+ setgroups
+ ;;
+ 5)
+ if echo "$crashcore" | grep -q 'singbox'; then
+ set_singbox_adv
+ else
+ set_clash_adv
+ fi
+ sleep 3
+ ;;
+ 9)
+ comp_box "\033[33m$OVR_WARN_1\033[0m" \
+ "\033[33m${OVR_WARN_2_PREFIX}$crashcore${OVR_WARN_2_SUFFIX}\033[0m" \
+ "\033[33m$OVR_WARN_3\033[0m"
+ sleep 2
+ btm_box "$OVR_WARN_CONFIRM" \
+ "$OVR_CONFIRM_NO"
+ read -r -p "$COMMON_INPUT> " res
+ [ "$res" = '1' ] && {
+ disoverride=1
+ if setconfig disoverride $disoverride; then
+ common_success
+ else
+ common_failed
+ fi
+ }
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
+}
+
+# 自定义规则
+setrules() {
+ set_rule_type() {
+ comp_box "\033[33m$OVR_RULES_TYPE\033[0m"
+ printf '%s\n' "$rule_type" |
+ awk '{for (i = 1; i <= NF; i++) print i") " $i}' |
+ while IFS= read -r line; do
+ content_line "$line"
+ done
+ btm_box "" \
+ "$OVR_BACK"
+ read -r -p "$OVR_INPUT_NUM" num
+ case "$num" in
+ "" | 0) ;;
+ [0-9]*)
+ if [ "$num" -gt $(echo $rule_type | awk -F " " '{print NF}') ]; then
+ errornum
+ else
+ rule_type_set=$(echo "$rule_type" | cut -d' ' -f"$num")
+ comp_box "\033[33m$OVR_RULES_ADD_RULE\033[0m"
+ read -r -p "$OVR_RULES_INPUT_RULE" rule_state_set
+ if [ -n "$rule_state_set" ]; then
+ set_group_type
+ else
+ errornum
+ fi
+ fi
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ }
+
+ set_group_type() {
+ comp_box "\033[36m$OVR_RULES_GROUP\033[0m" \
+ "\033[33m$OVR_RULES_EXIST_WARN\033[0m"
+ printf '%s\n' "$rule_group" |
+ awk -F '#' '{for (i = 1; i <= NF; i++) print i") " $i}' |
+ while IFS= read -r line; do
+ content_line "$line"
+ done
+ btm_box "" \
+ "$OVR_BACK"
+ read -r -p "$OVR_INPUT_NUM" num
+ case "$num" in
+ "" | 0) ;;
+ [0-9]*)
+ if [ "$num" -gt "$(echo "$rule_group" | awk -F "#" '{print NF}')" ]; then
+ errornum
+ 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
+ msg_alert "\033[32m$OVR_RULES_ADD_OK\033[0m"
+ fi
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ }
+
+ del_rule_type() {
+ while true; do
+ comp_box "$OVR_RULES_DEL_HINT"
+ sed -i '/^ *$/d; /^#/d' "$YAMLSDIR"/rules.yaml
+ awk -F '#' '!/^#/ {print NR") "$1 $2 $3}' "$YAMLSDIR/rules.yaml" |
+ while IFS= read -r line; do
+ content_line "$line"
+ done
+ btm_box "" \
+ "$OVR_BACK"
+ read -r -p "$OVR_INPUT_NUM" num
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ *)
+ if [ "$num" -le "$(wc -l <"$YAMLSDIR"/rules.yaml)" ]; then
+ if sed -i "${num}d" "$YAMLSDIR"/rules.yaml; then
+ common_success
+ else
+ common_failed
+ fi
+ sleep 1
+ else
+ errornum
+ 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
+ comp_box "\033[33m$OVR_RULES_MENU_HINT\033[0m" \
+ "$OVR_RULES_MANUAL" \
+ "\033[33m$OVR_RULES_SHARED\033[0m" \
+ "$OVR_RULES_WARN"
+ content_line "$OVR_RULES_ADD"
+ content_line "$OVR_RULES_DEL"
+ content_line "$OVR_RULES_CLEAR"
+ echo "$crashcore" | grep -q 'singbox' || content_line "$OVR_RULES_BYPASS \033[36m$proxies_bypass\033[0m"
+ content_line ""
+ content_line "$OVR_BACK"
+ separator_line "="
+ read -r -p "$OVR_INPUT_NUM" 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)
+ if [ -s "$YAMLSDIR"/rules.yaml ]; then
+ del_rule_type
+ else
+ msg_alert "$OVR_RULES_NO_RULES"
+ fi
+ ;;
+ 3)
+ comp_box "$OVR_RULES_CLEAR_CONFIRM"
+ btm_box "$OVR_CONFIRM_YES" \
+ "$OVR_CONFIRM_NO"
+ read -r -p "$COMMON_INPUT> " res
+ if [ "$res" = "1" ]; then
+ if sed -i '/^\s*[^#]/d' "$YAMLSDIR"/rules.yaml; then
+ common_success
+ else
+ common_failed
+ fi
+ fi
+ ;;
+ 4)
+ if [ "$proxies_bypass" = "OFF" ]; then
+ comp_box "\033[33m$OVR_RULES_BYPASS_WARN1\033[0m" \
+ "\033[33m$OVR_RULES_BYPASS_WARN2\033[0m" \
+ "" \
+ "$OVR_RULES_BYPASS_PROMPT"
+ btm_box "$OVR_CONFIRM_YES" \
+ "$OVR_CONFIRM_NO"
+ read -r -p "$COMMON_INPUT> " res
+ if [ "$res" = "1" ]; then
+ proxies_bypass=ON
+ else
+ continue
+ fi
+ else
+ proxies_bypass=OFF
+ fi
+
+ if setconfig proxies_bypass "$proxies_bypass"; then
+ common_success
+ else
+ common_failed
+ fi
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
+}
+
+# 自定义clash策略组
+setgroups() {
+ set_group_type() {
+ comp_box "\033[33m$OVR_GROUPS_WARN1\033[0m" \
+ "\033[33m$OVR_GROUPS_WARN2\033[0m" \
+ "\033[33m$OVR_GROUPS_WARN3\033[0m"
+ btm_box "\033[36m$OVR_GROUPS_INPUT_NAME\033[0m" \
+ "$OVR_CONFIRM_NO"
+ read -r -p "$OVR_PROMPT" new_group_name
+
+ comp_box "\033[32m$OVR_GROUPS_CHOOSE_TYPE【$new_group_name】\033[0m"
+ printf '%s\n' "$group_type_cn" |
+ awk '{for (i = 1; i <= NF; i++) print i") " $i}' |
+ while IFS= read -r line; do
+ content_line "$line"
+ done
+ separator_line "="
+ read -r -p "$OVR_GROUPS_INPUT_NUM" num
+ new_group_type=$(echo "$group_type" | awk '{print $'"$num"'}')
+ if [ "$num" = "1" ]; then
+ unset new_group_url interval
+ else
+ comp_box "$OVR_GROUPS_URL" \
+ "$OVR_GROUPS_URL_HINT"
+ read -r -p "$OVR_PROMPT" 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 </dev/null | sed "/#自定义策略组开始/,/#自定义策略组结束/d" | grep -Ev '^#' | grep -o '\- name:.*' | sed 's/#.*//' | sed 's/- name: /#/g' | tr -d '\n' | sed 's/#//')"
+ set_group_type
+ ;;
+ 2)
+ line_break
+ echo "==========================================================="
+ cat "$YAMLSDIR"/proxy-groups.yaml
+ echo ""
+ echo "==========================================================="
+ ;;
+ 3)
+ comp_box "$OVR_GROUPS_CLEAR_CONFIRM"
+ btm_box "$OVR_CONFIRM_YES" \
+ "$OVR_CONFIRM_NO"
+ read -r -p "$COMMON_INPUT> " res
+ if [ "$res" = "1" ]; then
+ if echo '#用于添加自定义策略组' >"$YAMLSDIR"/proxy-groups.yaml; then
+ common_success
+ else
+ common_failed
+ fi
+ fi
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
+}
+
+# 自定义clash节点
+setproxies() {
+
+ set_proxy_type() {
+ while true; do
+ comp_box "\033[33m$OVR_PROXIES_WARN1\033[0m" \
+ "\033[36m【name: \"test\", server: 192.168.1.1, port: 12345, type: socks5, udp: true】\033[0m" \
+ "$OVR_PROXIES_WARN2"
+ btm_box "\033[36m$OVR_PROXIES_INPUT\033[0m" \
+ "$OVR_CONFIRM_NO"
+ read -r -p "$OVR_PROMPT" proxy_state_set
+ if [ "$proxy_state_set" = 0 ]; then
+ break
+ elif echo "$proxy_state_set" | grep -q "#"; then
+ msg_alert "\033[33m$OVR_PROXIES_BLOCK_HASH\033[0m"
+ elif echo "$proxy_state_set" | grep -Eq "^name:"; then
+ set_group_add
+ else
+ errornum
+ fi
+ done
+ }
+
+ set_group_add() {
+ comp_box "\033[36m$OVR_PROXIES_ADD_HINT\033[0m" \
+ "\033[32m$OVR_PROXIES_MULTI_HINT\033[0m" \
+ "\033[33m$OVR_PROXIES_GROUP_HINT\033[0m"
+ printf '%s\n' "$proxy_group" |
+ awk -F '#' '{for (i = 1; i <= NF; i++) print i") " $i}' |
+ while IFS= read -r line; do
+ content_line "$line"
+ done
+ btm_box "" \
+ "$OVR_BACK"
+ read -r -p "$OVR_PROMPT" 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
+ msg_alert "\033[32m$OVR_PROXIES_ADD_OK\033[0m"
+ unset rule_group_add
+ else
+ errornum
+ fi
+ ;;
+ esac
+ }
+
+ while true; do
+ comp_box "\033[33m$OVR_PROXIES_MENU_HINT\033[0m" \
+ "\033[36m$OVR_PROXIES_MANUAL\033[0m"
+ btm_box "$OVR_PROXIES_ADD" \
+ "$OVR_PROXIES_MANAGE" \
+ "$OVR_PROXIES_CLEAR" \
+ "$OVR_PROXIES_BYPASS \033[36m$proxies_bypass\033[0m" \
+ "" \
+ "$OVR_BACK"
+ read -r -p "$OVR_INPUT_NUM" 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)
+ sed -i '/^ *$/d' "$YAMLSDIR"/proxies.yaml 2>/dev/null
+ if [ -s "$YAMLSDIR"/proxies.yaml ]; then
+ comp_box "\033[33m$OVR_PROXIES_EXIST_HINT\033[0m" \
+ "$OVR_PROXIES_EXIST_TITLE"
+ grep -Ev '^#' "$YAMLSDIR/proxies.yaml" |
+ awk -F '[,}]' '{print NR") " $1 " " $NF}' |
+ sed 's/- {//g' |
+ while IFS= read -r line; do
+ content_line "$line"
+ done
+ btm_box "" \
+ "$OVR_BACK"
+ read -r -p "$OVR_INPUT_NUM" num
+ if [ "$num" = 0 ]; then
+ continue
+ elif [ "$num" -le $(cat "$YAMLSDIR"/proxies.yaml | grep -Ev '^#' | wc -l) ]; then
+ if sed -i "$num{/^\s*[^#]/d}" "$YAMLSDIR"/proxies.yaml; then
+ common_success
+ else
+ common_failed
+ fi
+ else
+ errornum
+ fi
+ else
+ msg_alert "$OVR_PROXIES_NO_PROXY"
+ fi
+ ;;
+ 3)
+ comp_box "$OVR_PROXIES_CLEAR_CONFIRM"
+ btm_box "$OVR_CONFIRM_YES" \
+ "$OVR_CONFIRM_NO"
+ read -r -p "$COMMON_INPUT> " res
+ if [ "$res" = "1" ]; then
+ if sed -i '/^\s*[^#]/d' "$YAMLSDIR"/proxies.yaml 2>/dev/null; then
+ common_success
+ else
+ common_failed
+ fi
+ else
+ continue
+ fi
+ ;;
+ 4)
+ if [ "$proxies_bypass" = "OFF" ]; then
+ comp_box "\033[33m$OVR_PROXIES_BYPASS_WARN1\033[0m" \
+ "\033[33m$OVR_PROXIES_BYPASS_WARN2\033[0m" \
+ "" \
+ "$OVR_PROXIES_BYPASS_PROMPT"
+ btm_box "$OVR_CONFIRM_YES" \
+ "$OVR_CONFIRM_NO"
+ read -r -p "$COMMON_INPUT> " res
+ if [ "$res" = "1" ]; then
+ proxies_bypass=ON
+ else
+ continue
+ fi
+ else
+ proxies_bypass=OFF
+ fi
+ setconfig proxies_bypass "$proxies_bypass"
+ sleep 1
+ setrules
+ break
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
+}
+
+# 自定义clash高级规则
+set_clash_adv() {
+ [ ! -f "$YAMLSDIR"/user.yaml ] && cat >"$YAMLSDIR"/user.yaml <"$YAMLSDIR"/others.yaml < " num
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ if [ -s "$CRASHDIR"/configs/providers.cfg ] || [ -s "$CRASHDIR"/configs/providers_uri.cfg ]; then
+ . "$CRASHDIR/menus/providers_$CORE_TYPE.sh"
+ gen_providers
+ else
+ msg_alert "\033[31m$PROVIDERS_EMPTY_HINT\033[0m"
+ fi
+ ;;
+ 2)
+ list=$(cat "$CRASHDIR/configs/${CORE_TYPE}_providers.list" | awk '{print $1}')
+
+ comp_box "$PROVIDERS_TEMPLATE_CURRENT\033[32m$provider_temp_des\033[0m" \
+ "\033[33m$PROVIDERS_TEMPLATE_SELECT\033[0m"
+ list_box "$list"
+ btm_box "" \
+ "a) $PROVIDERS_TEMPLATE_LOCAL" \
+ "" \
+ "0) $COMMON_BACK"
+ read -r -p "$PROVIDERS_INPUT> " num
+ case "$num" in
+ "" | 0) ;;
+ a)
+ line_break
+ read -r -p "$PROVIDERS_TEMPLATE_PATH> " dir
+ if [ -s "$dir" ]; then
+ provider_temp_file=$dir
+ if setconfig provider_temp_"$CORE_TYPE" "$provider_temp_file"; then
+ common_success
+ else
+ common_failed
+ fi
+ else
+ msg_alert "\033[31m$PROVIDERS_TEMPLATE_NOT_FOUND\033[0m"
+ fi
+ ;;
+ *)
+ 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
+ else
+ if setconfig provider_temp_"$CORE_TYPE" "$provider_temp_file"; then
+ common_success
+ else
+ common_failed
+ fi
+ fi
+ ;;
+ esac
+ ;;
+ 3)
+ comp_box "\033[33m$PROVIDERS_CLEAN_WARN $CRASHDIR/providers $PROVIDERS_CLEAN_WARN_END\033[0m" \
+ "" \
+ "$PROVIDERS_CLEAN_CONFIRM"
+ btm_box "1) $PROVIDERS_YES" \
+ "0) $PROVIDERS_NO"
+ read -r -p "$COMMON_INPUT> " res
+ if [ "$res" = "1" ]; then
+ if rm -rf "$CRASHDIR"/providers; then
+ common_success
+ else
+ common_failed
+ fi
+ fi
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
+}
diff --git a/scripts/menus/providers_clash.sh b/scripts/menus/providers_clash.sh
new file mode 100644
index 00000000..f8bc313a
--- /dev/null
+++ b/scripts/menus/providers_clash.sh
@@ -0,0 +1,127 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+[ -n "$__IS_PROVIDERS_CLASH" ] && return
+__IS_PROVIDERS_CLASH=1
+
+load_lang providers
+
+. "$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
+
+ if [ -s "$provider_temp_file" ]; then
+ ln -sf "$provider_temp_file" "$TMPDIR"/provider_temp_file
+ else
+ msg_alert "\033[33m$PROVIDERS_FETCHING_TEMPLATE\033[0m"
+ get_bin "$TMPDIR"/provider_temp_file "rules/${CORE_TYPE}_providers/$provider_temp_file"
+ [ -z "$(grep -o 'rules' "$TMPDIR"/provider_temp_file)" ] && {
+ msg_alert "\033[31m$PROVIDERS_DOWNLOAD_FAILED\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 -r 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
+ msg_alert "\033[32m$PROVIDERS_GEN_OK\033[0m"
+ mkdir -p "$CRASHDIR"/yamls
+ mv -f "$TMPDIR"/config.yaml "$CRASHDIR"/yamls/config.yaml
+ comp_box "$PROVIDERS_RESTART_ASK"
+ btm_box "1) $PROVIDERS_YES" \
+ "0) $PROVIDERS_NO"
+ read -r -p "$COMMON_INPUT> " res
+ [ "$res" = 1 ] && {
+ start_core && . "$CRASHDIR"/libs/set_cron.sh && cronset "$PROVIDERS_CRON_SUB_UPDATE"
+ exit
+ }
+ else
+ rm -rf "$TMPDIR"/CrashCore
+ rm -rf "$TMPDIR"/config.yaml
+ msg_alert "\033[31m$PROVIDERS_GEN_FAILED\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 <>"$TMPDIR"/providers/providers.yaml <>"$TMPDIR"/providers/proxy-groups.yaml
+}
diff --git a/scripts/menus/providers_singbox.sh b/scripts/menus/providers_singbox.sh
new file mode 100644
index 00000000..26aa5b94
--- /dev/null
+++ b/scripts/menus/providers_singbox.sh
@@ -0,0 +1,138 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+[ -n "$__IS_PROVIDERS_SINGBOX" ] && return
+__IS_PROVIDERS_SINGBOX=1
+
+load_lang providers
+
+. "$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
+ if [ -s "$provider_temp_file" ]; then
+ ln -sf "$provider_temp_file" "$TMPDIR"/provider_temp_file
+ else
+ msg_alert "\033[33m$PROVIDERS_FETCHING_TEMPLATE\033[0m"
+ get_bin "$TMPDIR"/provider_temp_file "rules/${CORE_TYPE}_providers/$provider_temp_file"
+ [ -z "$(grep -o 'route' "$TMPDIR"/provider_temp_file)" ] && {
+ msg_alert "\033[31m$PROVIDERS_DOWNLOAD_FAILED\033[0m"
+ . "$CRASHDIR"/menus/9_upgrade.sh && setserver
+ setproviders
+ }
+ fi
+ # 生成outbound_providers模块
+ mkdir -p "$TMPDIR"/providers
+ # 预创建文件并写入对应文件头
+ cat >"$TMPDIR"/providers/providers.json <"$TMPDIR"/providers/outbounds_add.json <"$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
+ msg_alert "\033[32m$PROVIDERS_GEN_OK_SINGBOX\033[0m"
+ mkdir -p "$CRASHDIR"/jsons
+ mv -f "$TMPDIR"/config.json "$CRASHDIR"/jsons/config.json
+ rm -rf "$TMPDIR"/providerss
+ comp_box "$PROVIDERS_RESTART_ASK"
+ btm_box "1) $PROVIDERS_YES" \
+ "0) $PROVIDERS_NO"
+ read -r -p "$COMMON_INPUT> " res
+ [ "$res" = 1 ] && {
+ start_core && . "$CRASHDIR"/libs/set_cron.sh && cronset "$PROVIDERS_CRON_SUB_UPDATE"
+ exit
+ }
+ else
+ rm -rf "$TMPDIR"/CrashCore
+ msg_alert "\033[31m$PROVIDERS_GEN_FAILED\033[0m"
+ # rm -rf "$TMPDIR"/providers
+ fi
+}
+
+gen_providers_txt() {
+ tag=$1
+ interval=${3:-3}
+ interval2=${4:-12}
+ ua=${5:-clash.meta}
+ exclude=${6#\#}
+ include=${7#\#}
+ [ -n "$exclude" ] && exclude_ele="\"exclude\": \"$exclude\","
+ [ -n "$include" ] && include_ele="\"include\": \"$include\","
+ if [ -n "$(echo "$2" | grep -E '^./')" ]; then
+ cat >>"$TMPDIR"/providers/providers.json <>"$TMPDIR"/providers/providers.json <>"$TMPDIR"/providers/providers.json <>"$TMPDIR"/providers/outbounds_add.json
+}
diff --git a/scripts/menus/running_status.sh b/scripts/menus/running_status.sh
index 38419d2c..3da02535 100644
--- a/scripts/menus/running_status.sh
+++ b/scripts/menus/running_status.sh
@@ -1,13 +1,13 @@
running_status(){
- VmRSS=$(cat /proc/$PID/status | grep -w VmRSS | awk 'unit="MB" {printf "%.2f %s\n", $2/1000, unit}')
- #获取运行时长
- 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="$day天"
- time=$(date -u -d @${time} +%H小时%M分%S秒)
- fi
+ 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
}
diff --git a/scripts/menus/set_crashdir.sh b/scripts/menus/set_crashdir.sh
index 2f1be6c9..fe0e8fe2 100644
--- a/scripts/menus/set_crashdir.sh
+++ b/scripts/menus/set_crashdir.sh
@@ -1,150 +1,194 @@
#!/bin/sh
# Copyright (C) Juewuy
-. /tmp/SC_tmp/libs/check_dir_avail.sh
-[ -n "$(echo -e | grep e)" ] && echo=echo || echo='echo -e'
+[ -f /tmp/SC_tmp/libs/check_dir_avail.sh ] && . /tmp/SC_tmp/libs/check_dir_avail.sh
-set_crashdir() {
- set_usb_dir() {
- echo -e "请选择安装目录"
- du -hL /mnt | awk '{print " "NR" "$2" "$1}'
- read -p "请输入相应数字 > " num
+if [ -n "$CRASHDIR" ] && [ -s "$CRASHDIR/libs/i18n.sh" ]; then
+ . "$CRASHDIR/libs/i18n.sh"
+ load_lang set_crashdir
+elif [ -n "$language" ] && [ -s "/tmp/SC_tmp/lang/$language/set_crashdir.lang" ]; then
+ . "/tmp/SC_tmp/lang/$language/set_crashdir.lang"
+fi
+
+set_usb_dir() {
+ while true; do
+ comp_box "$SCD_SELECT_INSTALL_DIR"
+ du -hL /mnt |
+ awk '{print NR") "$2 " " $1}' |
+ while IFS= read -r line; do
+ content_line "$line"
+ done
+ separator_line "="
+ read -r -p "$SCD_INPUT_NUM> " 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
+ msg_alert "\033[31m$SCD_INPUT_ERROR\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
+ break 1
+ done
+}
+
+set_xiaomi_dir() {
+ comp_box "\033[33m$SCD_XIAOMI_DETECTED\033[0m"
+ [ -d /data ] && content_line "1) /data$SCD_DIR_FREE$(dir_avail /data -h) $SCD_SOFT_SOLID"
+ [ -d /userdisk ] && content_line "2) /userdisk$SCD_DIR_FREE$(dir_avail /userdisk -h) $SCD_SOFT_SOLID"
+ [ -d /data/other_vol ] && content_line "3) /data/other_vol$SCD_DIR_FREE$(dir_avail /data/other_vol -h) $SCD_SOFT_SOLID"
+ content_line "4) $SCD_CUSTOM_DIR_WARN"
+ content_line ""
+ content_line "0) $SCD_EXIT_INSTALL"
+ separator_line "="
+ read -r -p "$SCD_INPUT_NUM> " num
+ case "$num" in
+ 1)
+ dir=/data
+ ;;
+ 2)
+ dir=/userdisk
+ ;;
+ 3)
+ dir=/data/other_vol
+ ;;
+ 4)
+ set_cust_dir
+ ;;
+ *)
+ line_break
+ exit 1
+ ;;
+ esac
+}
+
+set_asus_usb() {
+ while true; do
+ comp_box "$SCD_SELECT_USB_DIR"
+ du -hL /tmp/mnt |
+ awk -F/ 'NF<=4 {print NR") "$2 " " $1}' |
+ while IFS= read -r line; do
+ content_line "$line"
+ done
+ separator_line "="
+ read -r -p "$SCD_INPUT_NUM> " 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"
+ msg_alert "\033[31m$SCD_ASUS_DM_NOT_FOUND $dir/asusware.arm/etc/init.d/S50downloadmaster,$SCD_CHECK_SETTING\033[0m"
+ else
+ break
+ fi
+ done
+}
+
+set_asus_dir() {
+ separator_line "="
+ btm_box "\033[33m$SCD_ASUS_DETECTED\033[0m" \
+ "1) $SCD_ASUS_INSTALL_DM" \
+ "2) $SCD_ASUS_INSTALL_SCRIPT" \
+ "" \
+ "0) $SCD_EXIT_INSTALL"
+ read -r -p "$SCD_INPUT_NUM> " num
+ case "$num" in
+ 1)
+ msg_alert -t 2 "$SCD_ASUS_DM_HINT"
+ set_asus_usb
+ ;;
+ 2)
+ msg_alert -t 2 "$SCD_ASUS_REINSTALL_HINT"
+ dir=/jffs
+ ;;
+ *)
+ line_break
+ exit 1
+ ;;
+ esac
+}
+
+set_cust_dir() {
+ while true; do
+ comp_box "$SCD_PATH_FORMAT_HINT" \
+ "" \
+ "$SCD_PATH_FREE_SPACE"
+ df -h |
+ awk '{print $6, $4}' |
+ sed '1d' |
+ while IFS= read -r line; do
+ content_line "$line"
+ done
+ separator_line "="
+ read -r -p "$SCD_INPUT_CUSTOM_DIR> " dir
+ if [ "$(dir_avail "$dir")" = 0 ] || [ -n "$(echo "$dir" | grep -Eq '^/(tmp|opt|sys)(/|$)')" ]; then
+ msg_alert "\033[31m$SCD_PATH_ERROR\033[0m"
+ continue
+ fi
+ break 1
+ done
+}
+
+set_crashdir() {
+ while true; do
+ top_box "\033[33m$SCD_INSTALL_SPACE_HINT\033[0m"
+ case "$systype" in
+ Padavan)
+ dir=/etc/storage
+ ;;
+ mi_snapshot)
+ set_xiaomi_dir
+ ;;
+ asusrouter)
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
+ ;;
+ ng_snapshot)
+ dir=/tmp/mnt
+ ;;
+ *)
+ separator_line "="
+ btm_box "1) $SCD_INSTALL_ETC" \
+ "2) $SCD_INSTALL_USR" \
+ "3) $SCD_INSTALL_HOME" \
+ "4) $SCD_INSTALL_USB" \
+ "5) $SCD_INSTALL_MANUAL" \
+ "" \
+ "0) $SCD_EXIT_INSTALL"
+ read -r -p "$SCD_INPUT_NUM> " num
+ # 设置目录
case "$num" in
1)
- dir=/data
+ dir=/etc
;;
2)
- dir=/userdisk
+ dir=/usr/share
;;
3)
- dir=/data/other_vol
+ dir=~/.local/share
+ mkdir -p ~/.config/systemd/user
;;
4)
+ set_usb_dir
+ ;;
+ 5)
set_cust_dir
;;
*)
+ msg_alert "$SCD_INSTALL_CANCELED"
+ line_break
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
+ if [ ! -w "$dir" ]; then
+ msg_alert "\033[31m$SCD_NO_WRITE_PREFIX$dir$SCD_NO_WRITE_SUFFIX\033[0m"
+ else
+ comp_box "$SCD_TARGET_DIR_PREFIX\033[32m$dir\033[0m$SCD_TARGET_DIR_SPACE$(dir_avail "$dir" -h)" \
+ "" \
+ "$SCD_CONFIRM_INSTALL"
+ btm_box "1) $SCD_YES" \
+ "0) $SCD_NO"
+ read -r -p "$SCD_INPUT_NUM> " res
+ if [ "$res" = "1" ]; then
+ CRASHDIR="$dir"/ShellCrash
+ break
+ fi
+ fi
+ done
}
-
diff --git a/scripts/menus/subconverter.sh b/scripts/menus/subconverter.sh
new file mode 100644
index 00000000..17f04ad1
--- /dev/null
+++ b/scripts/menus/subconverter.sh
@@ -0,0 +1,223 @@
+#!/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
+
+load_lang subconverter
+
+LISTFILE="$CRASHDIR"/configs/servers_"$i18n".list
+
+# Subconverter在线订阅转换
+subconverter() {
+ while true; do
+ comp_box "1) \033[32m$SUBCONVERTER_MENU_GEN\033[0m"\
+ "2) $SUBCONVERTER_MENU_EXCLUDE \033[47;30m$exclude\033[0m"\
+ "3) $SUBCONVERTER_MENU_INCLUDE \033[47;30m$include\033[0m"\
+ "4) $SUBCONVERTER_MENU_RULE"\
+ "5) $SUBCONVERTER_MENU_SERVER"\
+ "6) $SUBCONVERTER_MENU_UA \033[32m$user_agent\033[0m"\
+ ""\
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ providers_link=$(grep -v '\./providers/' "$CRASHDIR"/configs/providers.cfg 2>/dev/null | awk '{print $2}' | tr '\n' '|')
+ uri_link=$(grep -v '^#' "$CRASHDIR"/configs/providers_uri.cfg 2>/dev/null | awk '{ print ($1=="vmess" ? $2 : $2 "#" $1) }' | tr '\n' '|')
+ Url=$(echo "$providers_link|$uri_link" | sed 's/||*/|/g; 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
+ ;;
+ esac
+ done
+}
+
+# 排除节点正则
+gen_link_flt() {
+ comp_box "\033[33m$SUBCONVERTER_EXCLUDE_HINT1\033[0m" \
+ "$SUBCONVERTER_KEYWORD_SPLIT" \
+ "$SUBCONVERTER_REGEX_HINT"
+ btm_box "\033[36m$SUBCONVERTER_EXCLUDE_INPUT\033[0m" \
+ "$SUBCONVERTER_EXCLUDE_CLEAR" \
+ "$SUBCONVERTER_BACK"
+ read -r -p "$SUBCONVERTER_INPUT> " res
+ case "$res" in
+ 0)
+ return 0
+ ;;
+ d)
+ exclude=''
+ ;;
+ *)
+ exclude="$res"
+ ;;
+ esac
+
+ if setconfig exclude "'$exclude'"; then
+ common_success
+ else
+ common_failed
+ fi
+}
+
+# 包含节点正则
+gen_link_ele() {
+ comp_box "\033[33m$SUBCONVERTER_INCLUDE_HINT1\033[0m" \
+ "$SUBCONVERTER_KEYWORD_SPLIT" \
+ "$SUBCONVERTER_REGEX_HINT"
+ btm_box "\033[36m$SUBCONVERTER_INCLUDE_INPUT\033[0m" \
+ "$SUBCONVERTER_INCLUDE_CLEAR" \
+ "$SUBCONVERTER_BACK"
+ read -r -p "$SUBCONVERTER_INPUT> " res
+ case "$res" in
+ 0)
+ return 0
+ ;;
+ d)
+ include=""
+ ;;
+ *)
+ include="$res"
+ ;;
+ esac
+
+ if setconfig include "'$include'"; then
+ common_success
+ else
+ common_failed
+ fi
+}
+
+# 选择在线规则模版
+gen_link_config() {
+ list=$(grep -aE '^5' "$LISTFILE" | awk '{print $2$4}')
+ now=$(grep -aE '^5' "$LISTFILE" | sed -n ""$rule_link"p" | awk '{print $2}')
+ comp_box "$SUBCONVERTER_RULE_CURRENT\033[33m$now\033[0m"
+ list_box "$list"
+ content_line ""
+ common_back
+ read -r -p "$COMMON_INPUT> " num
+ totalnum=$(grep -acE '^5' "$CRASHDIR"/configs/servers_"$i18n".list)
+ if [ -z "$num" ] || [ "$num" -gt "$totalnum" ]; then
+ errornum
+ elif [ "$num" = 0 ]; then
+ echo
+ elif [ "$num" -le "$totalnum" ]; then
+ # 将对应标记值写入配置
+ rule_link=$num
+ if setconfig rule_link "$rule_link"; then
+ msg_alert "\033[32m$SUBCONVERTER_SET_OK\033[0m"
+ else
+ common_failed
+ fi
+ fi
+}
+
+# 选择Subconverter服务器
+gen_link_server() {
+ list=$(grep -aE '^3|^4' "$LISTFILE" | awk '{print $3" "$2}')
+ now=$(grep -aE '^3|^4' "$LISTFILE" | sed -n ""$server_link"p" | awk '{print $3}')
+
+ comp_box "\033[36m$SUBCONVERTER_SERVER_HINT\033[0m" \
+ "\033[32m$SUBCONVERTER_SERVER_THANKS\033[0m" \
+ "" \
+ "$SUBCONVERTER_SERVER_CURRENT\033[33m$now\033[0m"
+ list_box "$list"
+ content_line ""
+ common_back
+ read -r -p "$COMMON_INPUT> " num
+ totalnum=$(grep -acE '^3|^4' "$CRASHDIR"/configs/servers_"$i18n".list)
+ if [ -z "$num" ] || [ "$num" -gt "$totalnum" ]; then
+ errornum
+ elif [ "$num" = 0 ]; then
+ echo
+ elif [ "$num" -le "$totalnum" ]; then
+ # 将对应标记值写入配置
+ server_link=$num
+ if setconfig server_link "$server_link"; then
+ content_line "\033[32m$SUBCONVERTER_SET_OK\033[0m"
+ else
+ common_failed
+ fi
+ fi
+}
+
+set_sub_ua() {
+ while true; do
+ comp_box "\033[36m$SUBCONVERTER_UA_HINT\033[0m" \
+ "" \
+ "$SUBCONVERTER_UA_CURRENT$user_agent"
+ btm_box "1) $SUBCONVERTER_UA_AUTO"\
+ "2) $SUBCONVERTER_UA_NONE"\
+ "3) $SUBCONVERTER_UA_CUSTOM"\
+ "4) $SUBCONVERTER_UA_CLEAR"\
+ ""\
+ "0) $COMMON_BACK"
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ 0)
+ break
+ ;;
+ 1)
+ user_agent='auto'
+ ;;
+ 2)
+ user_agent='none'
+ ;;
+ 3)
+ comp_box "\033[33m$SUBCONVERTER_UA_CUSTOM_WARN\033[0m"
+ btm_box "\033[36m$SUBCONVERTER_UA_CUSTOM_INPUT\033[0m" \
+ "$SUBCONVERTER_BACK"
+ read -r -p "$SUBCONVERTER_INPUT> " text
+ if [ "$text" = 0 ]; then
+ continue
+ elif [ -n "$text" ]; then
+ user_agent="$text"
+ fi
+ ;;
+ 4)
+ user_agent=''
+ ;;
+ *)
+ errornum
+ continue
+ ;;
+ esac
+
+ if [ "$num" -ge 1 ] && [ "$num" -le 4 ]; then
+ if setconfig user_agent "$user_agent"; then
+ common_success
+ else
+ common_failed
+ fi
+ fi
+ break
+ done
+}
diff --git a/scripts/menus/task_cmd.sh b/scripts/menus/task_cmd.sh
index 4e39bd25..0b1982e2 100644
--- a/scripts/menus/task_cmd.sh
+++ b/scripts/menus/task_cmd.sh
@@ -9,123 +9,127 @@
. "$CRASHDIR"/libs/set_config.sh
. "$CRASHDIR"/libs/web_get_bin.sh
. "$CRASHDIR"/libs/logger.sh
+. "$CRASHDIR"/libs/i18n.sh
+[ -z "$TASKCFGDIR" ] && TASKCFGDIR="$CRASHDIR"/configs/task
+
+load_lang task_cmd
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])分钟' && {
- push=off
- cover=on
- }
- logger "$1" 0 "$push" "$cover"
+ [ "$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 "($TASK_CMD_EVERY|$TASK_CMD_HOURLY)([1-9]|[1-9][0-9])$TASK_CMD_MIN" && {
+ push=off
+ cover=on
+ }
+ logger "$1" 0 "$push" "$cover"
}
#任务命令
check_update(){ #检查更新工具
- get_bin "$TMPDIR"/crashversion "$1" echooff
- [ "$?" = "0" ] && . "$TMPDIR"/crashversion 2>/dev/null
- rm -rf "$TMPDIR"/crashversion
+ 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_tools.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
+ #检查版本
+ 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 "$TASK_CMD_CORE_SKIP"
+ return 0
+ else
+ . "$CRASHDIR"/libs/core_tools.sh && core_webget #调用下载工具
+ case "$?" in
+ 0)
+ task_logger "$TASK_CMD_CORE_DONE"
+ "$CRASHDIR"/start.sh start
+ return 0
+ ;;
+ 1)
+ task_logger "$TASK_CMD_CORE_DL_FAIL"
+ return 1
+ ;;
+ *)
+ task_logger "$TASK_CMD_CORE_VERIFY_FAIL"
+ "$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"/ShellCrash.tar.gz "ShellCrash.tar.gz"
- if [ "$?" != "0" ];then
- rm -rf "$TMPDIR"/ShellCrash.tar.gz
- task_logger "任务【自动更新内核】出错-下载失败!"
- return 1
- else
- #停止服务
- "$CRASHDIR"/start.sh stop
- #解压
- tar -zxf "$TMPDIR"/ShellCrash.tar.gz ${tar_para} -C "$CRASHDIR"/
- if [ $? -ne 0 ];then
- rm -rf "$TMPDIR"/ShellCrash.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
+ #检查版本
+ check_update version
+ if [ -z "$versionsh" -o "$versionsh" = "versionsh_l" ];then
+ task_logger "$TASK_CMD_SCRIPT_SKIP"
+ return 0
+ else
+ get_bin "$TMPDIR"/ShellCrash.tar.gz "ShellCrash.tar.gz"
+ if [ "$?" != "0" ];then
+ rm -rf "$TMPDIR"/ShellCrash.tar.gz
+ task_logger "$TASK_CMD_CORE_DL_FAIL"
+ return 1
+ else
+ #停止服务
+ "$CRASHDIR"/start.sh stop
+ #解压
+ tar -zxf "$TMPDIR"/ShellCrash.tar.gz ${tar_para} -C "$CRASHDIR"/
+ if [ $? -ne 0 ];then
+ rm -rf "$TMPDIR"/ShellCrash.tar.gz
+ task_logger "$TASK_CMD_SCRIPT_UNZIP_FAIL"
+ "$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
+ 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 "$TASK_CMD_DB_SKIP_PREFIX$2$TASK_CMD_DB_SKIP_SUFFIX"
+ else
+ #更新文件
+ get_bin "$TMPDIR"/$1 "bin/geodata/$2"
+ if [ "$?" != "0" ];then
+ task_logger "$TASK_CMD_DB_DL_FAIL_PREFIX$2$TASK_CMD_DB_DL_FAIL_SUFFIX"
+ rm -rf "$TMPDIR"/$1
+ else
+ mv -f "$TMPDIR"/$1 "$BINDIR"/$1
+ setconfig $geo_v $GeoIP_v
+ task_logger "$TASK_CMD_DB_OK_PREFIX$2$TASK_CMD_DB_OK_SUFFIX"
+ 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
+ "$CRASHDIR"/start.sh stop_firewall
+ "$CRASHDIR"/start.sh afstart
}
ntp(){
- ckcmd ntpd && ntpd -n -q -p 203.107.6.88 >/dev/null 2>&1 || exit 0
+ 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
+ . "$CRASHDIR"/libs/web_save.sh && web_save
}
update_config() { #更新订阅并重启
- . "$CRASHDIR"/starts/core_config.sh && get_core_config && "$CRASHDIR"/start.sh start
+ . "$CRASHDIR"/starts/core_config.sh get_core_config && "$CRASHDIR"/start.sh start
}
hotupdate() { #热更新订阅
. "$CRASHDIR"/starts/core_config.sh && get_core_config &&
@@ -136,14 +140,14 @@ hotupdate() { #热更新订阅
}
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"
- ;;
+ [1-9][0-9][0-9])
+ task_command=$(cat "$CRASHDIR"/task/task_${i18n}.list "$TASKCFGDIR"/task.user 2>/dev/null | grep "$1" | awk -F '#' '{print $2}')
+ task_name=$(cat "$CRASHDIR"/task/task_${i18n}.list "$TASKCFGDIR"/task.user 2>/dev/null | grep "$1" | awk -F '#' '{print $3}')
+ #task_logger "任务$task_name 开始执行"
+ eval $task_command && task_res="$TASK_CMD_RES_OK" || task_res="$TASK_CMD_RES_FAIL"
+ task_logger "$TASK_CMD_EXEC_PREFIX$2$TASK_CMD_EXEC_MID$task_res"
+ ;;
+ *)
+ "$1"
+ ;;
esac
diff --git a/scripts/menus/tui_layout.sh b/scripts/menus/tui_layout.sh
new file mode 100644
index 00000000..5f3bcea3
--- /dev/null
+++ b/scripts/menus/tui_layout.sh
@@ -0,0 +1,148 @@
+# 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 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"
+}
diff --git a/scripts/menus/tui_lite.sh b/scripts/menus/tui_lite.sh
new file mode 100644
index 00000000..377da03a
--- /dev/null
+++ b/scripts/menus/tui_lite.sh
@@ -0,0 +1,18 @@
+
+TABLE_WIDTH=60
+
+content_line() {
+ printf '%b' " $1\n"
+}
+
+sub_content_line() {
+ content_line " $1"
+}
+
+separator_line() {
+ echo "-----------------------------------------------"
+}
+
+line_break() {
+ return
+}
diff --git a/scripts/menus/uninstall.sh b/scripts/menus/uninstall.sh
index 4fe3bfda..57b00920 100644
--- a/scripts/menus/uninstall.sh
+++ b/scripts/menus/uninstall.sh
@@ -1,19 +1,29 @@
#!/bin/sh
# Copyright (C) Juewuy
-#卸载
+load_lang uninstall
+
+# 卸载
uninstall() {
- read -p "确认卸载ShellCrash?(警告:该操作不可逆!)[1/0] > " res
+ comp_box "\033[31m$UNINSTALL_WARN\033[0m" \
+ "$UNINSTALL_CONFIRM"
+ btm_box "1) $UNINSTALL_YES" \
+ "0) $UNINSTALL_NO"
+ 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 "$UNINSTALL_CRON_CLASH" 2>/dev/null
+ "$CRASHDIR"/start.sh cronset "$UNINSTALL_CRON_SUB" 2>/dev/null
+ "$CRASHDIR"/start.sh cronset "$UNINSTALL_CRON_INIT" 2>/dev/null
"$CRASHDIR"/start.sh cronset "task.sh" 2>/dev/null
- #移除安装目录
+
+ # 移除安装目录
if [ -n "$CRASHDIR" ] && [ "$CRASHDIR" != '/' ]; then
- read -p "是否保留脚本配置及订阅文件?[1/0] > " res
+ comp_box "$UNINSTALL_KEEP_CONFIRM"
+ btm_box "1) $UNINSTALL_YES" \
+ "0) $UNINSTALL_NO"
+ 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
@@ -26,10 +36,10 @@ uninstall() {
rm -rf "$CRASHDIR"
fi
else
- echo -e "\033[31m环境变量配置有误,请尝试手动移除安装目录!\033[0m"
- sleep 1
+ msg_alert "\033[31m$UNINSTALL_ENV_ERROR\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
@@ -40,9 +50,9 @@ uninstall() {
}
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
+ sed -i "/$UNINSTALL_SSH_MARK/d" /etc/firewall.user 2>/dev/null
+ sed -i "/$UNINSTALL_CRON_INIT/d" /etc/storage/started_script.sh 2>/dev/null
+ sed -i "/$UNINSTALL_CRON_INIT/d" /jffs/.asusrouter 2>/dev/null
[ "$BINDIR" != "$CRASHDIR" ] && rm -rf "$BINDIR"
rm -rf /etc/init.d/shellcrash
rm -rf /etc/systemd/system/shellcrash.service
@@ -54,12 +64,12 @@ uninstall() {
userdel -r shellcrash 2>/dev/null
nvram set script_usbmount="" 2>/dev/null
nvram commit 2>/dev/null
- echo "-----------------------------------------------"
- echo -e "\033[36m已卸载ShellCrash相关文件!有缘再会!\033[0m"
- echo -e "\033[33m请手动关闭当前窗口以重置环境变量!\033[0m"
- echo "-----------------------------------------------"
- exit
+ comp_box "\033[36m$UNINSTALL_DONE\033[0m" \
+ "\033[33m$UNINSTALL_CLOSE_HINT\033[0m"
+ line_break
+ sleep 1
+ exit 0
else
- echo -e "\033[31m操作已取消!\033[0m"
+ msg_alert "\033[31m$UNINSTALL_CANCELED\033[0m"
fi
}
diff --git a/scripts/menus/userguide.sh b/scripts/menus/userguide.sh
new file mode 100644
index 00000000..4595633e
--- /dev/null
+++ b/scripts/menus/userguide.sh
@@ -0,0 +1,147 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+[ -n "$__IS_MODULE_USERGUIDE_LOADED" ] && return
+__IS_MODULE_USERGUIDE_LOADED=1
+
+. "$CRASHDIR"/libs/check_dir_avail.sh
+
+select_lang() {
+ line_break
+ comp_box "1) 简体中文" \
+ "2) English"
+ read -r -p "请选择语言 Please choose your language > " num
+ case "$num" in
+ 1)
+ echo chs >"$CRASHDIR"/configs/i18n.cfg
+ ;;
+ 2)
+ echo en >"$CRASHDIR"/configs/i18n.cfg
+ ;;
+ esac
+ line_break
+ load_lang menu
+ load_lang common
+ load_lang userguide
+}
+
+forwhat() {
+ while true; do
+ comp_box "\033[30;46m$UG_WELCOME\033[0m" \
+ "" \
+ "\033[33m$UG_CHOOSE_ENV\033[0m" \
+ "\033[0m$UG_TIP_CONFIG\033[0m"
+
+ content_line "1) \033[32m$UG_OPTION_1\033[0m"
+ content_line "2) \033[36m$UG_OPTION_2\033[0m"
+ [ -s "$CRASHDIR"/configs.tar.gz ] && content_line "3) \033[33m$UG_OPTION_3\033[0m"
+ separator_line "="
+ read -r -p "$COMMON_INPUT> " num
+ case "$num" in
+ "" | 1)
+ # 设置运行模式
+ redir_mod="Mix"
+ content_line "$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
+ separator_line "-"
+ content_line "\033[33m$UG_IP_FORWARD_WARN\033[0m"
+ read -r -p "$COMMON_INPUT_R" res
+ [ "$res" = 1 ] && {
+ content_line 'net.ipv4.ip_forward = 1' >>/etc/sysctl.conf
+ sysctl -w net.ipv4.ip_forward=1
+ }
+ 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"
+ content_line "$cputype" | grep -Eq "linux.*mips.*" && setconfig crashcore "clash"
+ setconfig common_ports "OFF"
+ setconfig firewall_area '2'
+ break
+ ;;
+ 3)
+ tar -zxf "$CRASHDIR"/configs.tar.gz -C "$CRASHDIR"/configs
+ msg_alert "\033[32m$UG_RESTORE_OK\033[0m"
+ line_break
+ exit 0
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ done
+}
+
+# 新手引导
+userguide() {
+
+ select_lang
+
+ forwhat
+
+ # 检测小内存模式
+ dir_size=$(dir_avail "$CRASHDIR")
+ if [ "$dir_size" -lt 10240 ]; then
+ comp_box "\033[33m$UG_ENABLE_LOW_MEM\033[0m"
+ read -r -p "$COMMON_INPUT_R" res
+ [ "$res" = 1 ] && {
+ BINDIR=/tmp/ShellCrash
+ sed -i "s#BINDIR=.*#BINDIR=$BINDIR#" "$CRASHDIR"/configs/command.env
+ }
+ fi
+
+ # 启用推荐的自动任务配置
+ . "$CRASHDIR"/menus/5_task.sh && task_recom
+
+ # 提示导入订阅或者配置文件
+ if [ ! -s "$CRASHDIR"/yamls/config.yaml ] && [ ! -s "$CRASHDIR"/jsons/config.json ]; then
+ comp_box "\033[0m$UG_IMPORT_CONFIG\033[0m" \
+ "\033[32m$UG_CONFIG_TIP\033[0m" \
+ "$UG_CONFIG_RES"
+ btm_box "1) $UG_IMPORT_NOW" \
+ "0) $UG_IMPORT_LATER"
+ read -r -p "$COMMON_INPUT> " res
+ [ "$res" = 1 ] && inuserguide=1 && {
+ . "$CRASHDIR"/menus/6_core_config.sh && set_core_config
+ inuserguide=""
+ }
+ fi
+
+ # 回到主界面
+ msg_alert "\033[36m$UG_FINAL_TIP\033[0m"
+ return 0
+}
diff --git a/scripts/start.sh b/scripts/start.sh
index 03c3cc0f..97e9247f 100644
--- a/scripts/start.sh
+++ b/scripts/start.sh
@@ -16,20 +16,20 @@
. "$CRASHDIR"/libs/web_save.sh
#特殊脚本
bfstart(){
- "$CRASHDIR"/starts/bfstart.sh
+ "$CRASHDIR"/starts/bfstart.sh
}
afstart(){
- "$CRASHDIR"/starts/afstart.sh
+ "$CRASHDIR"/starts/afstart.sh
}
stop_firewall(){
- "$CRASHDIR"/starts/fw_stop.sh
+ "$CRASHDIR"/starts/fw_stop.sh
}
#保守模式启动
start_l(){
- bfstart && {
- . "$CRASHDIR"/starts/start_legacy.sh
- start_legacy "$COMMAND" 'shellcrash'
- } && afstart &
+ bfstart && {
+ . "$CRASHDIR"/starts/start_legacy.sh
+ start_legacy "$COMMAND" 'shellcrash'
+ } && afstart &
}
case "$1" in
@@ -37,26 +37,26 @@ case "$1" in
start)
[ -n "$(pidof CrashCore)" ] && $0 stop #禁止多实例
stop_firewall #清理路由策略
- rm -f "$CRASHDIR"/\.start_error #移除自启失败标记
+ rm -f "$CRASHDIR"/\.start_error #移除自启失败标记
#使用不同方式启动服务
- if [ "$firewall_area" = "5" ]; then #主旁转发
+ if [ "$firewall_area" = "5" ]; then #主旁转发
. "$CRASHDIR"/starts/fw_start.sh
elif [ "$start_old" = "ON" ]; then
start_l
elif [ -f /etc/rc.common ] && grep -q 'procd' /proc/1/comm; then
/etc/init.d/shellcrash start
elif [ "$USER" = "root" ] && grep -q 'systemd' /proc/1/comm; then
- FragmentPath=$(systemctl show -p FragmentPath shellcrash | sed 's/FragmentPath=//')
- [ -f "$FragmentPath" ] && {
- sed -i "s#^ExecStart=.*#ExecStart=$COMMAND >/dev/null#" "$FragmentPath"
- systemctl daemon-reload
- }
- systemctl start shellcrash.service || . "$CRASHDIR"/starts/start_error.sh
+ FragmentPath=$(systemctl show -p FragmentPath shellcrash | sed 's/FragmentPath=//')
+ [ -f "$FragmentPath" ] && {
+ sed -i "s#^ExecStart=.*#ExecStart=$COMMAND >/dev/null#" "$FragmentPath"
+ systemctl daemon-reload
+ }
+ systemctl start shellcrash.service || . "$CRASHDIR"/starts/start_error.sh
elif grep -q 's6' /proc/1/comm; then
- bfstart && /command/s6-svc -u /run/service/shellcrash && {
- [ ! -f "$CRASHDIR"/.dis_startup ] && touch /etc/s6-overlay/s6-rc.d/user/contents.d/afstart
- afstart &
- }
+ bfstart && /command/s6-svc -u /run/service/shellcrash && {
+ [ ! -f "$CRASHDIR"/.dis_startup ] && touch /etc/s6-overlay/s6-rc.d/user/contents.d/afstart
+ afstart &
+ }
elif rc-status -r >/dev/null 2>&1; then
rc-service shellcrash stop >/dev/null 2>&1
rc-service shellcrash start
@@ -65,12 +65,12 @@ start)
fi
;;
stop)
- logger ShellCrash服务即将关闭……
+ logger ShellCrash服务即将关闭......
[ -n "$(pidof CrashCore)" ] && web_save #保存面板配置
#清理定时任务
- cronload | grep -vE '^$|start_legacy_wd.sh|运行时每' > "$TMPDIR"/cron_tmp
- cronadd "$TMPDIR"/cron_tmp
- rm -f "$TMPDIR"/cron_tmp
+ cronload | grep -vE '^$|start_legacy_wd.sh|运行时每' > "$TMPDIR"/cron_tmp
+ cronadd "$TMPDIR"/cron_tmp
+ rm -f "$TMPDIR"/cron_tmp
#停止tg_bot
. "$CRASHDIR"/menus/bot_tg_service.sh && bot_tg_stop
#多种方式结束进程
@@ -83,8 +83,8 @@ stop)
elif [ -f /etc/rc.common ] && grep -q 'procd' /proc/1/comm; then
/etc/init.d/shellcrash stop >/dev/null 2>&1
elif grep -q 's6' /proc/1/comm; then
- /command/s6-svc -d /run/service/shellcrash
- stop_firewall
+ /command/s6-svc -d /run/service/shellcrash
+ stop_firewall
elif rc-status -r >/dev/null 2>&1; then
rc-service shellcrash stop >/dev/null 2>&1
else
diff --git a/scripts/starts/afstart.sh b/scripts/starts/afstart.sh
index a9da9869..d798a517 100644
--- a/scripts/starts/afstart.sh
+++ b/scripts/starts/afstart.sh
@@ -2,7 +2,11 @@
# Copyright (C) Juewuy
#初始化目录
-[ -z "$CRASHDIR" ] && CRASHDIR=$( cd $(dirname $0);cd ..;pwd)
+[ -z "$CRASHDIR" ] && CRASHDIR=$(
+ cd $(dirname $0)
+ cd ..
+ pwd
+)
. "$CRASHDIR"/libs/get_config.sh
#加载工具
. "$CRASHDIR"/libs/check_cmd.sh
@@ -18,13 +22,13 @@
#设置循环检测面板端口以判定服务启动是否成功
. "$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 #标记启动时间
- #后台还原面板配置
+ [ "$start_old" = "ON" ] && [ ! -L "$TMPDIR"/CrashCore ] && rm -f "$TMPDIR"/CrashCore #删除缓存目录内核文件
+ . "$CRASHDIR"/starts/fw_start.sh #配置防火墙流量劫持
+ date +%s >"$TMPDIR"/crash_start_time #标记启动时间
+ #还原面板配置
[ -s "$CRASHDIR"/configs/web_save ] && {
. "$CRASHDIR"/libs/web_restore.sh
- web_restore >/dev/null 2>&1 &
+ web_restore >/dev/null 2>&1
}
#推送日志
{
@@ -33,22 +37,22 @@ if [ -n "$test" -o -n "$(pidof CrashCore)" ]; then
} &
ckcmd mtd_storage.sh && mtd_storage.sh save >/dev/null 2>&1 #Padavan保存/etc/storage
#加载定时任务
- cronload | grep -v '^$' > "$TMPDIR"/cron_tmp
- [ -s "$CRASHDIR"/task/cron ] && cat "$CRASHDIR"/task/cron >> "$TMPDIR"/cron_tmp
- [ -s "$CRASHDIR"/task/running ] && cat "$CRASHDIR"/task/running >> "$TMPDIR"/cron_tmp
- [ "$bot_tg_service" = ON ] && echo "* * * * * /bin/sh $CRASHDIR/starts/start_legacy_wd.sh bot_tg #ShellCrash-TG_BOT守护进程" >> "$TMPDIR"/cron_tmp
- [ "$start_old" = ON ] && echo "* * * * * /bin/sh $CRASHDIR/starts/start_legacy_wd.sh shellcrash #ShellCrash保守模式守护进程" >> "$TMPDIR"/cron_tmp
- awk '!x[$0]++' "$TMPDIR"/cron_tmp > "$TMPDIR"/cron_tmp2 #删除重复行
+ cronload | grep -v '^$' >"$TMPDIR"/cron_tmp
+ [ -s "$TASKCFGDIR"/cron ] && cat "$TASKCFGDIR"/cron >>"$TMPDIR"/cron_tmp
+ [ -s "$TASKCFGDIR"/running ] && cat "$TASKCFGDIR"/running >>"$TMPDIR"/cron_tmp
+ [ "$bot_tg_service" = ON ] && echo "* * * * * /bin/sh $CRASHDIR/starts/start_legacy_wd.sh bot_tg #ShellCrash-TG_BOT守护进程" >>"$TMPDIR"/cron_tmp
+ [ "$start_old" = ON ] && echo "* * * * * /bin/sh $CRASHDIR/starts/start_legacy_wd.sh shellcrash #ShellCrash保守模式守护进程" >>"$TMPDIR"/cron_tmp
+ awk '!x[$0]++' "$TMPDIR"/cron_tmp >"$TMPDIR"/cron_tmp2 #删除重复行
cronadd "$TMPDIR"/cron_tmp2
rm -f "$TMPDIR"/cron_tmp "$TMPDIR"/cron_tmp2
#加载条件任务
- [ -s "$CRASHDIR"/task/afstart ] && { . "$CRASHDIR"/task/afstart; } &
- [ -s "$CRASHDIR"/task/affirewall -a -s /etc/init.d/firewall -a ! -f /etc/init.d/firewall.bak ] && {
+ [ -s "$TASKCFGDIR"/afstart ] && { . "$TASKCFGDIR"/afstart; } &
+ [ -s "$TASKCFGDIR"/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
+ sed -i.bak "${line}a\\. $TASKCFGDIR/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
+ sed -i "${line}a\\. $TASKCFGDIR/affirewall" /etc/init.d/firewall
} &
exit 0
else
diff --git a/scripts/starts/bfstart.sh b/scripts/starts/bfstart.sh
index b0c3eb45..ce8450f8 100644
--- a/scripts/starts/bfstart.sh
+++ b/scripts/starts/bfstart.sh
@@ -5,7 +5,7 @@
[ -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"
+[ ! -d "$TMPDIR" ] && mkdir -p "$TMPDIR"
#当上次启动失败时终止自启动
[ -f "$CRASHDIR"/.start_error ] && exit 1
@@ -18,7 +18,7 @@
. "$CRASHDIR"/starts/check_geo.sh
. "$CRASHDIR"/starts/check_core.sh
#缺省值
-[ -z "$redir_mod" ] && [ "$USER" = "root" -o "$USER" = "admin" ] && redir_mod='Redir模式'
+[ -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))
@@ -38,8 +38,8 @@ makehtml() { #生成面板跳转文件
您还未安装本地面板
-
请在脚本更新功能中(9-4)安装
或者使用在线面板:
-
请复制当前地址/ui(不包括)前面的内容,填入url位置即可连接
+ 请在脚本更新功能中(9-4)安装
或者使用在线面板:
+
@@ -54,19 +54,19 @@ catpac() { #生成pac文件
[ -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 </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
+ [ -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" = "混合模式" ] && ckcmd modprobe && modprobe tun 2>/dev/null
+[ "$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
-
diff --git a/scripts/starts/check_core.sh b/scripts/starts/check_core.sh
index a8815398..9c99b9a3 100644
--- a/scripts/starts/check_core.sh
+++ b/scripts/starts/check_core.sh
@@ -5,7 +5,7 @@
check_core() { #检查及下载内核文件
[ -n "$(find --help 2>&1 | grep -o size)" ] && find_para=' -size +2000' #find命令兼容
- [ -z "$(find "$TMPDIR"/CrashCore $find_para 2>/dev/null)" ] && core_find
+ [ -z "$(find "$TMPDIR"/CrashCore $find_para 2>/dev/null)" ] && core_find
[ ! -f "$TMPDIR"/CrashCore ] && {
logger "未找到【$crashcore】核心,正在下载!" 33
[ -z "$cpucore" ] && . "$CRASHDIR"/libs/check_cpucore.sh && check_cpucore
diff --git a/scripts/starts/clash_check.sh b/scripts/starts/clash_check.sh
index 8200ed19..93460537 100644
--- a/scripts/starts/clash_check.sh
+++ b/scripts/starts/clash_check.sh
@@ -5,8 +5,8 @@ clash_check() { #clash启动前检查
#检测是否存在高级版规则或者tun模式
if [ "$crashcore" = "clash" ]; then
[ -n "$(cat $core_config | grep -aiE '^script:|proxy-providers|rule-providers|rule-set')" ] ||
- [ "$redir_mod" = "混合模式" ] ||
- [ "$redir_mod" = "Tun模式" ] && core_exchange meta '当前内核不支持的配置'
+ [ "$redir_mod" = "Mix" ] ||
+ [ "$redir_mod" = "Tun" ] && core_exchange meta '当前内核不支持的配置'
fi
[ "$crashcore" = "clash" ] && [ "$firewall_area" = 2 -o "$firewall_area" = 3 ] && [ -z "$(grep '0:7890' /etc/passwd)" ] &&
core_exchange meta '当前内核不支持非root用户启用本机代理'
diff --git a/scripts/starts/clash_modify.sh b/scripts/starts/clash_modify.sh
index 24a91282..493c0e20 100644
--- a/scripts/starts/clash_modify.sh
+++ b/scripts/starts/clash_modify.sh
@@ -1,12 +1,11 @@
#!/bin/sh
# Copyright (C) Juewuy
-#修饰clash配置文件
-modify_yaml() {
+prepare_clash_base_config() {
##########需要变更的配置###########
[ "$ipv6_dns" != "OFF" ] && dns_v6='true' || dns_v6='false'
external="external-controller: 0.0.0.0:$db_port"
- if [ "$redir_mod" = "混合模式" -o "$redir_mod" = "Tun模式" ]; then
+ if [ "$redir_mod" = "Mix" -o "$redir_mod" = "Tun" ]; then
[ "$crashcore" = 'meta' ] && tun_meta=', device: utun, auto-route: false, auto-detect-interface: false'
tun="tun: {enable: true, stack: system$tun_meta}"
else
@@ -15,16 +14,16 @@ modify_yaml() {
exper='experimental: {ignore-resolve-fail: true, interface-name: en0}'
#Meta内核专属配置
[ "$crashcore" = 'meta' ] && {
- [ "$redir_mod" != "纯净模式" ] && [ -z "$(grep 'PROCESS' "$CRASHDIR"/yamls/*.yaml)" ] && find_process='find-process-mode: "off"'
- #ecs优化
- [ "$ecs_subnet" = ON ] && {
- . "$CRASHDIR"/libs/get_ecsip.sh
- if [ -n "$ecs_address" ];then
- dns_fallback=$(echo "$dns_fallback, " | sed "s|, |#ecs-override=true\&ecs=$ecs_address, |g" | sed 's|, $||')
- else
- logger "自动获取ecs网段失败!"
- fi
- }
+ [ -z "$(grep 'PROCESS' "$CRASHDIR"/yamls/*.yaml)" ] && find_process='find-process-mode: "off"'
+ #ecs优化
+ [ "$ecs_subnet" = ON ] && {
+ . "$CRASHDIR"/libs/get_ecsip.sh
+ if [ -n "$ecs_address" ];then
+ dns_fallback=$(echo "$dns_fallback, " | sed "s|, |#ecs-override=true\&ecs=$ecs_address, |g" | sed 's|, $||')
+ else
+ logger "自动获取ecs网段失败!" 33
+ fi
+ }
}
#dns配置
[ -z "$(cat "$CRASHDIR"/yamls/user.yaml 2>/dev/null | grep '^dns:')" ] && {
@@ -38,7 +37,7 @@ dns:
default-nameserver: [ $dns_resolver ]
direct-nameserver: [ $dns_nameserver ]
enhanced-mode: fake-ip
- fake-ip-range: 28.0.0.0/8
+ fake-ip-range: 198.18.0.0/15
fake-ip-range6: fc00::/16
fake-ip-filter:
EOF
@@ -55,7 +54,7 @@ EOF
cat >>"$TMPDIR"/dns.yaml <"$TMPDIR"/set.yaml <>"$TMPDIR"/hosts.yaml
fi
- #加载本机hosts
- sys_hosts=/etc/hosts
- [ -f /data/etc/custom_hosts ] && sys_hosts='/etc/hosts /data/etc/custom_hosts'
- cat $sys_hosts | while read line; do
- [ -n "$(echo "$line" | grep -oE "([0-9]{1,3}[\.]){3}")" ] &&
- [ -z "$(echo "$line" | grep -oE '^#')" ] &&
- hosts_ip=$(echo $line | awk '{print $1}') &&
- hosts_domain=$(echo $line | awk '{print $2}') &&
- [ -z "$(cat "$TMPDIR"/hosts.yaml | grep -oE "$hosts_domain")" ] &&
- echo " '$hosts_domain': $hosts_ip" >>"$TMPDIR"/hosts.yaml
- done
+ #加载本机hosts
+ sys_hosts=/etc/hosts
+ [ -f /data/etc/custom_hosts ] && sys_hosts='/etc/hosts /data/etc/custom_hosts'
+ cat $sys_hosts | while read line; do
+ [ -n "$(echo "$line" | grep -oE "([0-9]{1,3}[\.]){3}")" ] &&
+ [ -z "$(echo "$line" | grep -oE '^#')" ] &&
+ hosts_ip=$(echo $line | awk '{print $1}') &&
+ hosts_domain=$(echo $line | awk '{print $2}') &&
+ [ -z "$(cat "$TMPDIR"/hosts.yaml | grep -oE "$hosts_domain")" ] &&
+ echo " '$hosts_domain': $hosts_ip" >>"$TMPDIR"/hosts.yaml
+ done
fi
+}
+
+split_and_customize_yaml_parts() {
#分割配置文件
yaml_char='proxies proxy-groups proxy-providers rules rule-providers sub-rules listeners'
for char in $yaml_char; do
@@ -171,11 +176,14 @@ EOF
IFS="$oldIFS"
done
}
+}
+
+add_custom_inbounds_and_rules() {
#添加自定义入站
- [ "$vms_service" = ON ] || [ "$sss_service" = ON ] && {
- . "$CRASHDIR"/configs/gateway.cfg
- . "$CRASHDIR"/libs/meta_listeners.sh
- }
+ [ "$vms_service" = ON ] || [ "$sss_service" = ON ] && {
+ . "$CRASHDIR"/configs/gateway.cfg
+ . "$CRASHDIR"/libs/meta_listeners.sh
+ }
#节点绕过功能支持
sed -i "/#节点绕过/d" "$TMPDIR"/rules.yaml
[ "$proxies_bypass" = "ON" ] && {
@@ -191,11 +199,14 @@ EOF
cat "$TMPDIR"/rules.yaml >>"$TMPDIR"/rules.add
mv -f "$TMPDIR"/rules.add "$TMPDIR"/rules.yaml
}
+}
+
+merger_yaml() {
#mix和route模式生成rule-providers
[ "$dns_mod" = "mix" ] || [ "$dns_mod" = "route" ] && ! grep -Eq '^[[:space:]]*cn:' "$TMPDIR"/rule-providers.yaml && ! grep -q '^rule-providers' "$CRASHDIR"/yamls/others.yaml 2>/dev/null && {
space=$(sed -n "1p" "$TMPDIR"/rule-providers.yaml | grep -oE '^ *') #获取空格数
[ -z "$space" ] && space=' '
- echo "${space}cn: {type: http, behavior: domain, format: mrs, path: ./ruleset/cn.mrs, url: https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@update/bin/geodata/mrs_geosite_cn.mrs}" >>"$TMPDIR"/rule-providers.yaml
+ echo "${space}cn: {type: http, behavior: domain, format: mrs, path: ./ruleset/cn.mrs, interval: 86400, url: https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@update/bin/geodata/mrs_geosite_cn.mrs}" >>"$TMPDIR"/rule-providers.yaml
}
#对齐rules中的空格
sed -i 's/^ *-/ -/g' "$TMPDIR"/rules.yaml
@@ -220,6 +231,9 @@ EOF
done
#合并完整配置文件
cut -c 1- "$TMPDIR"/set.yaml $yaml_dns $yaml_hosts $yaml_user $yaml_others $yaml_add >"$TMPDIR"/config.yaml
+}
+
+test_yaml() {
#测试自定义配置文件
"$TMPDIR"/CrashCore -t -d "$BINDIR" -f "$TMPDIR"/config.yaml >/dev/null
if [ "$?" != 0 ]; then
@@ -233,10 +247,24 @@ EOF
cut -c 1- "$TMPDIR"/set.yaml $yaml_dns $yaml_add >"$TMPDIR"/config.yaml
sed -i "/#自定义/d" "$TMPDIR"/config.yaml
fi
+}
+
+finalize_clash_yaml() {
#建立软连接
[ ""$TMPDIR"" = ""$BINDIR"" ] || ln -sf "$TMPDIR"/config.yaml "$BINDIR"/config.yaml 2>/dev/null || cp -f "$TMPDIR"/config.yaml "$BINDIR"/config.yaml
#清理缓存
for char in $yaml_char set set_bak dns hosts; do
rm -f "$TMPDIR"/${char}.yaml
done
-}
\ No newline at end of file
+}
+
+#修饰clash配置文件
+modify_yaml() {
+ prepare_clash_base_config
+ generate_set_and_hosts_yaml
+ split_and_customize_yaml_parts
+ add_custom_inbounds_and_rules
+ merger_yaml
+ test_yaml
+ finalize_clash_yaml
+}
diff --git a/scripts/starts/core_config.sh b/scripts/starts/core_config.sh
index dd2462c2..256b3a68 100644
--- a/scripts/starts/core_config.sh
+++ b/scripts/starts/core_config.sh
@@ -6,17 +6,21 @@
. "$CRASHDIR"/libs/web_get_bin.sh
. "$CRASHDIR"/libs/compare.sh
. "$CRASHDIR"/libs/set_config.sh
+. "$CRASHDIR"/libs/logger.sh
+. "$CRASHDIR"/libs/i18n.sh
-update_servers() { #更新servers.list
- get_bin "$TMPDIR"/servers.list public/servers.list
- [ "$?" = 0 ] && mv -f "$TMPDIR"/servers.list "$CRASHDIR"/configs/servers.list
+load_lang
+
+update_servers() { #更新servers_${i18n}.list
+ get_bin "$TMPDIR"/servers_${i18n}.list public/servers_${i18n}.list
+ [ "$?" = 0 ] && mv -f "$TMPDIR"/servers_${i18n}.list "$CRASHDIR"/configs/servers_${i18n}.list
}
gen_ua(){ #自动生成ua
[ -z "$user_agent" -o "$user_agent" = "auto" ] && {
if echo "$crashcore" | grep -q 'singbox'; then
- user_agent="sing-box/singbox/$core_v"
+ user_agent="sing-box/$core_v"
elif [ "$crashcore" = meta ]; then
- user_agent="clash.meta/mihomo/$core_v"
+ user_agent="clash.meta/mihomo"
else
user_agent="clash"
fi
@@ -25,28 +29,28 @@ gen_ua(){ #自动生成ua
}
get_core_config() { #下载内核配置文件
[ -z "$rule_link" ] && rule_link=1
- [ -z "$server_link" ] || [ $server_link -gt $(grep -aE '^4' "$CRASHDIR"/configs/servers.list | wc -l) ] && server_link=1
- Server=$(grep -aE '^3|^4' "$CRASHDIR"/configs/servers.list | sed -n ""$server_link"p" | awk '{print $3}')
- Server_ua=$(grep -aE '^4' "$CRASHDIR"/configs/servers.list | sed -n ""$server_link"p" | awk '{print $4}')
- Config=$(grep -aE '^5' "$CRASHDIR"/configs/servers.list | sed -n ""$rule_link"p" | awk '{print $3}')
+ [ -z "$server_link" ] || [ $server_link -gt $(grep -aE '^4' "$CRASHDIR"/configs/servers_${i18n}.list | wc -l) ] && server_link=1
+ Server=$(grep -aE '^3|^4' "$CRASHDIR"/configs/servers_${i18n}.list | sed -n ""$server_link"p" | awk '{print $3}')
+ Server_ua=$(grep -aE '^4' "$CRASHDIR"/configs/servers_${i18n}.list | sed -n ""$server_link"p" | awk '{print $4}')
+ Config=$(grep -aE '^5' "$CRASHDIR"/configs/servers_${i18n}.list | sed -n ""$rule_link"p" | awk '{print $3}')
gen_ua
- #如果传来的是Url链接则合成Https链接,否则直接使用Https链接
+ #如果传来的是Url链接则合成Https链接,否则直接使用Https链接
if [ -z "$Https" ]; then
#Urlencord转码处理保留字符
if ckcmd hexdump;then
- Url=$(echo $Url | sed 's/%26/\&/g') #处理分隔符
- urlencodeUrl="exclude=$(urlencode "$exclude")&include=$(urlencode "$include")&url=$(urlencode "$Url")&config=$(urlencode "$Config")"
- else
- urlencodeUrl="exclude=$exclude&include=$include&url=$Url&config=$Config"
- fi
+ Url=$(echo $Url | sed 's/%26/\&/g') #处理分隔符
+ urlencodeUrl="exclude=$(urlencode "$exclude")&include=$(urlencode "$include")&url=$(urlencode "$Url")&config=$(urlencode "$Config")"
+ else
+ urlencodeUrl="exclude=$exclude&include=$include&url=$Url&config=$Config"
+ fi
Https="${Server}/sub?target=${target}&${Server_ua}=${user_agent}&insert=true&new_name=true&scv=true&udp=true&${urlencodeUrl}"
url_type=true
- else
- Https=$(echo $Https | sed 's/\\&/\&/g') #还原转义
+ else
+ Https=$(echo $Https | sed 's/\\&/\&/g') #还原转义
fi
#输出
echo "-----------------------------------------------"
- logger "正在连接服务器获取【$target】配置文件…………"
+ logger "正在连接服务器获取【$target】配置文件…………" 36
echo -e "链接地址为:\033[4;32m$Https\033[0m"
echo 可以手动复制该链接到浏览器打开并查看数据是否正常!
#获取在线config文件
@@ -91,7 +95,7 @@ get_core_config() { #下载内核配置文件
else
. "$CRASHDIR"/starts/clash_config_check.sh
fi
- check_config
+ check_config
#如果不同则备份并替换文件
if [ -s "$core_config" ]; then
compare "$core_config_new" "$core_config"
diff --git a/scripts/starts/fw_getlanip.sh b/scripts/starts/fw_getlanip.sh
index 2849bcbe..2d9e3a39 100644
--- a/scripts/starts/fw_getlanip.sh
+++ b/scripts/starts/fw_getlanip.sh
@@ -1,36 +1,45 @@
-
getlanip() { #获取局域网host地址
i=1
while [ "$i" -le "20" ]; do
- host_ipv4=$(ip route show scope link | grep -Ev 'wan|utun|iot|peer|docker|podman|virbr|vnet|ovs|vmbr|veth|vmnic|vboxnet|lxcbr|xenbr|vEthernet' | awk '{print $1}') #ipv4局域网网段
- [ "$ipv6_redir" = "ON" ] && host_ipv6=$(ip -6 route show default | awk '{print $3}' | tr '\n' ' ' | sed 's/ $//') #ipv6公网地址段
+ #ipv4局域网网段
+ host_ipv4=$(ip route show scope link | grep -Ev 'default|wan|utun|iot|peer|docker|podman|virbr|vnet|ovs|vmbr|veth|vmnic|vboxnet|lxcbr|xenbr|vEthernet|wgs|multicast|anycast' | awk '{print $1}')
+ #ipv6局域网网段 - 从IPv4已识别的LAN接口获取全局IPv6前缀
+ [ "$ipv6_redir" = "ON" ] && {
+ lan_ifaces=$(ip route show scope link | grep -Ev 'ppp|wan|utun|iot|peer|docker|podman|virbr|vnet|ovs|vmbr|veth|vmnic|vboxnet|lxcbr|xenbr|vEthernet|wgs|multicast|anycast' | awk '{for(i=1;i<=NF;i++) if($i=="dev") {print $(i+1); break}}' | grep -v '^lo$' | sort -u)
+ host_ipv6=$(
+ for iface in $lan_ifaces; do
+ ip -6 addr show dev $iface 2>/dev/null
+ done | grep 'scope global' | awk '{print $2}' | tr '\n' ' ' | sed 's/ $//'
+ )
+ [ -z "$host_ipv6" ] && host_ipv6=$(ip -6 route show | grep -Ev 'default|unreachable|fe80::/|wan|ppp|utun|iot|peer|docker|podman|virbr|vnet|ovs|vmbr|veth|vmnic|vboxnet|lxcbr|xenbr|vEthernet|wgs|multicast|anycast' | awk '{print $1}' | tr '\n' ' ' | sed 's/ $//')
+ }
[ -f "$TMPDIR"/ShellCrash.log ] && break
[ -n "$host_ipv4" -a "$ipv6_redir" != "ON" ] && break
[ -n "$host_ipv4" -a -n "$host_ipv6" ] && break
sleep 1 && i=$((i + 1))
done
- #Tailscale
- [ "$ts_service" = ON ] && {
- ts_host_ipv4=' 100.64.0.0/10'
- ts_host_ipv6=' fd7a:115c:a1e0::/48'
- }
- #Wireguard
- [ "$wg_service" = ON ] && {
- . "$CRASHDIR"/configs/gateway.cfg
- wg_host_ipv4=' $wg_ipv4'
- [ -n "$wg_ipv6" ] && wg_host_ipv6=' $wg_ipv6'
- }
+ #Tailscale
+ [ "$ts_service" = ON ] && {
+ ts_host_ipv4=' 100.64.0.0/10'
+ ts_host_ipv6=' fd7a:115c:a1e0::/48'
+ }
+ #Wireguard
+ [ "$wg_service" = ON ] && {
+ . "$CRASHDIR"/configs/gateway.cfg
+ wg_host_ipv4=' $wg_ipv4'
+ [ -n "$wg_ipv6" ] && wg_host_ipv6=' $wg_ipv6'
+ }
#添加自定义ipv4局域网网段
- if [ "$replace_default_host_ipv4" == "ON" ]; then
+ if [ "$replace_default_host_ipv4" = "ON" ]; then
host_ipv4="$cust_host_ipv4"
else
- host_ipv4=$(echo "$host_ipv4 $cust_host_ipv4$ts_host_ipv4$wg_host_ipv4"| tr '\n' ' ' | sed 's/ $//')
+ host_ipv4=$(echo "$host_ipv4 $cust_host_ipv4$ts_host_ipv4$wg_host_ipv4" | tr '\n' ' ' | sed 's/ $//')
fi
#缺省配置
[ -z "$host_ipv4" ] && {
- host_ipv4='192.168.0.0/16 10.0.0.0/12 172.16.0.0/12'
- logger "无法获取本地LAN-IPV4网段,请前往流量过滤设置界面设置自定义网段!" 31
- }
+ host_ipv4='192.168.0.0/16 10.0.0.0/12 172.16.0.0/12'
+ logger "无法获取本地LAN-IPV4网段,请前往流量过滤设置界面设置自定义网段!" 31
+ }
host_ipv6="fe80::/10 fd00::/8 $host_ipv6$ts_host_ipv6$wg_host_ipv6"
#获取本机出口IP地址
local_ipv4=$(ip route 2>&1 | grep -Ev 'utun|iot|docker|linkdown' | grep -Eo 'src.*' | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | sort -u)
@@ -38,4 +47,4 @@ getlanip() { #获取局域网host地址
#保留地址
[ -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"
[ -z "$reserve_ipv6" ] && reserve_ipv6="::/128 ::1/128 ::ffff:0:0/96 64:ff9b::/96 100::/64 2001::/32 2001:20::/28 2001:db8::/32 2002::/16 fe80::/10 ff00::/8"
-}
\ No newline at end of file
+}
diff --git a/scripts/starts/fw_iptables.sh b/scripts/starts/fw_iptables.sh
index 8105bb7a..8e02c0d0 100644
--- a/scripts/starts/fw_iptables.sh
+++ b/scripts/starts/fw_iptables.sh
@@ -32,11 +32,12 @@ start_ipt_route() { #iptables-route通用工具
done
[ "$firewall_area" = 5 ] && "$1" $w -t "$2" -A "$4" -s $bypass_host -j RETURN
[ -z "$ports" ] && {
- "$1" $w -t "$2" -A "$4" -p tcp -m multiport --dports "$mix_port,$redir_port,$tproxy_port" -j RETURN
- "$1" $w -t "$2" -A "$4" -p udp -m multiport --dports "$mix_port,$redir_port,$tproxy_port" -j RETURN
- }
+ "$1" $w -t "$2" -A "$4" -p tcp -m multiport --dports "$mix_port,$redir_port,$tproxy_port" -j RETURN
+ "$1" $w -t "$2" -A "$4" -p udp -m multiport --dports "$mix_port,$redir_port,$tproxy_port" -j RETURN
+ }
#跳过目标保留地址及目标本机网段
for ip in $HOST_IP $RESERVED_IP; do
+ [ "$ip" = "default" ] && continue
"$1" $w -t "$2" -A "$4" -d $ip -j RETURN
done
#绕过CN_IP
@@ -65,13 +66,29 @@ start_ipt_route() { #iptables-route通用工具
"$1" $w -t "$2" -A "$4" -p "$5" -s $ip -j $JUMP
done
else
- for ip in $HOST_IP; do #仅限指定网段流量
+ for ip in $HOST_IP; do #仅限指定网段流量 (已修复 default 报错)
+ [ "$ip" = "default" ] && continue
"$1" $w -t "$2" -A "$4" -p "$5" -s $ip -j $JUMP
done
fi
#将所在链指定流量指向shellcrash表
- "$1" $w -t "$2" -I "$3" -p "$5" $ports -j "$4"
- [ "$dns_mod" = "mix" -o "$dns_mod" = "fake-ip" ] && [ "$common_ports" = "ON" ] && [ "$1" = iptables ] && "$1" $w -t "$2" -I "$3" -p "$5" -d 28.0.0.0/8 -j "$4"
+ if [ -n "$ports" ]; then
+ clean_ports=$(echo "$multiport" | sed 's/ //g')
+ echo "$clean_ports" | awk -F, '{
+ for(i=1; i<=NF; i+=9) {
+ group=""
+ for(j=i; j/dev/null 2>&1
JUMP="TPROXY --on-port $tproxy_port --tproxy-mark $fwmark" #跳转劫持的具体命令
if $iptable -j TPROXY -h 2>/dev/null | grep -q '\--on-port'; then
@@ -230,14 +248,14 @@ start_iptables() { #iptables配置总入口
fi
}
}
- [ "$redir_mod" = "Tun模式" -o "$redir_mod" = "混合模式" -o "$redir_mod" = "T&U旁路转发" -o "$redir_mod" = "TCP旁路转发" ] && {
+ [ "$redir_mod" = "Tun" -o "$redir_mod" = "Mix" -o "$redir_mod" = "T&U旁路转发" -o "$redir_mod" = "TCP旁路转发" ] && {
JUMP="MARK --set-mark $fwmark" #跳转劫持的具体命令
- [ "$redir_mod" = "Tun模式" -o "$redir_mod" = "T&U旁路转发" ] && protocol=all
- [ "$redir_mod" = "混合模式" ] && protocol=udp
+ [ "$redir_mod" = "Tun" -o "$redir_mod" = "T&U旁路转发" ] && protocol=all
+ [ "$redir_mod" = "Mix" ] && protocol=udp
[ "$redir_mod" = "TCP旁路转发" ] && protocol=tcp
if $iptable -j MARK -h 2>/dev/null | grep -q '\--set-mark'; then
[ "$lan_proxy" = true ] && {
- [ "$redir_mod" = "Tun模式" -o "$redir_mod" = "混合模式" ] && $iptable -I FORWARD -o utun -j ACCEPT
+ [ "$redir_mod" = "Tun" -o "$redir_mod" = "Mix" ] && $iptable -I FORWARD -o utun -j ACCEPT
start_ipt_route iptables mangle PREROUTING shellcrash_mark $protocol
}
[ "$local_proxy" = true ] && start_ipt_route iptables mangle OUTPUT shellcrash_mark_out $protocol
@@ -247,7 +265,7 @@ start_iptables() { #iptables配置总入口
[ "$ipv6_redir" = "ON" ] && [ "$crashcore" != clashpre ] && {
if $ip6table -j MARK -h 2>/dev/null | grep -q '\--set-mark'; then
[ "$lan_proxy" = true ] && {
- [ "$redir_mod" = "Tun模式" -o "$redir_mod" = "混合模式" ] && $ip6table -I FORWARD -o utun -j ACCEPT
+ [ "$redir_mod" = "Tun" -o "$redir_mod" = "Mix" ] && $ip6table -I FORWARD -o utun -j ACCEPT
start_ipt_route ip6tables mangle PREROUTING shellcrashv6_mark $protocol
}
[ "$local_proxy" = true ] && start_ipt_route ip6tables mangle OUTPUT shellcrashv6_mark_out $protocol
@@ -256,7 +274,8 @@ start_iptables() { #iptables配置总入口
fi
}
}
- [ "$vm_redir" = "ON" ] && [ -n "$$vm_ipv4" ] && {
+ # 修复了原本双刀号 $$vm_ipv4 会变为进程 PID_ipv4 的语法错误问题
+ [ "$vm_redir" = "ON" ] && [ -n "$vm_ipv4" ] && {
JUMP="REDIRECT --to-ports $redir_port" #跳转劫持的具体命令
start_ipt_dns iptables PREROUTING shellcrash_vm_dns #ipv4-局域网dns转发
start_ipt_route iptables nat PREROUTING shellcrash_vm tcp #ipv4-局域网tcp转发
@@ -275,18 +294,18 @@ start_iptables() { #iptables配置总入口
[ "$local_proxy" = true ] && start_ipt_dns iptables OUTPUT shellcrash_dns_out #ipv4-本机dns转发
}
#屏蔽QUIC
- [ "$quic_rj" = 'ON' -a "$lan_proxy" = true -a "$redir_mod" != "Redir模式" ] && {
+ [ "$quic_rj" = 'ON' -a "$lan_proxy" = true -a "$redir_mod" != "Redir" ] && {
[ "$dns_mod" != "fake-ip" -a "$cn_ip_route" = "ON" ] && {
set_cn_ip='-m set ! --match-set cn_ip dst'
set_cn_ip6='-m set ! --match-set cn_ip6 dst'
}
- [ "$redir_mod" = "Tun模式" -o "$redir_mod" = "混合模式" ] && {
+ [ "$redir_mod" = "Tun" -o "$redir_mod" = "Mix" ] && {
$iptable -I FORWARD -p udp --dport 443 -o utun $set_cn_ip -j REJECT >/dev/null 2>&1
$ip6table -I FORWARD -p udp --dport 443 -o utun $set_cn_ip6 -j REJECT >/dev/null 2>&1
}
- [ "$redir_mod" = "Tproxy模式" ] && {
+ [ "$redir_mod" = "Tproxy" ] && {
$iptable -I INPUT -p udp --dport 443 $set_cn_ip -j REJECT >/dev/null 2>&1
$ip6table -I INPUT -p udp --dport 443 $set_cn_ip6 -j REJECT >/dev/null 2>&1
}
}
-}
+}
\ No newline at end of file
diff --git a/scripts/starts/fw_nftables.sh b/scripts/starts/fw_nftables.sh
index 1600cd35..c1d5e2c9 100644
--- a/scripts/starts/fw_nftables.sh
+++ b/scripts/starts/fw_nftables.sh
@@ -5,24 +5,24 @@ RESERVED_IP=$(echo $reserve_ipv4 | sed 's/[[:space:]]\+/, /g')
RESERVED_IP6=$(echo "$reserve_ipv6 $host_ipv6" | sed 's/[[:space:]]\+/, /g')
add_ip6_route(){
- #过滤保留地址及本机地址
- nft add rule inet shellcrash $1 ip6 daddr {$RESERVED_IP6} return
- #仅代理本机局域网网段流量
- nft add rule inet shellcrash $1 ip6 saddr != {$HOST_IP6} return
- #绕过CN_IPV6
- [ "$dns_mod" != "fake-ip" -a "$cn_ip_route" = "ON" -a -f "$BINDIR"/cn_ipv6.txt ] && {
- CN_IP6=$(awk '{printf "%s, ",$1}' "$BINDIR"/cn_ipv6.txt)
- [ -n "$CN_IP6" ] && {
- nft add set inet shellcrash cn_ip6 { type ipv6_addr \; flags interval \; }
- nft add element inet shellcrash cn_ip6 { $CN_IP6 }
- nft add rule inet shellcrash $1 ip6 daddr @cn_ip6 return
- }
- }
+ #过滤保留地址及本机地址
+ nft add rule inet shellcrash $1 ip6 daddr {$RESERVED_IP6} return
+ #仅代理本机局域网网段流量
+ nft add rule inet shellcrash $1 ip6 saddr != {$HOST_IP6} return
+ #绕过CN_IPV6
+ [ "$dns_mod" != "fake-ip" -a "$cn_ip_route" = "ON" -a -f "$BINDIR"/cn_ipv6.txt ] && {
+ CN_IP6=$(awk '{printf "%s, ",$1}' "$BINDIR"/cn_ipv6.txt)
+ [ -n "$CN_IP6" ] && {
+ nft add set inet shellcrash cn_ip6 { type ipv6_addr \; flags interval \; }
+ nft add element inet shellcrash cn_ip6 { $CN_IP6 }
+ nft add rule inet shellcrash $1 ip6 daddr @cn_ip6 return
+ }
+ }
}
start_nft_route() { #nftables-route通用工具
#$1:name $2:hook(prerouting/output) $3:type(nat/mangle/filter) $4:priority(-100/-150)
[ "$common_ports" = "ON" ] && PORTS=$(echo $multiport | sed 's/,/, /g')
- [ "$1" = 'prerouting' ] && HOST_IP=$(echo $host_ipv4 | sed 's/[[:space:]]\+/, /g')
+ [ "$1" = 'prerouting' ] && HOST_IP=$(echo $host_ipv4 | sed 's/[[:space:]]\+/, /g')
[ "$1" = 'output' ] && HOST_IP="127.0.0.0/8, $(echo $local_ipv4 | sed 's/[[:space:]]\+/, /g')"
[ "$1" = 'prerouting_vm' ] && HOST_IP="$(echo $vm_ipv4 | sed 's/[[:space:]]\+/, /g')"
#添加新链
@@ -38,12 +38,12 @@ start_nft_route() { #nftables-route通用工具
[ -z "$ports" ] && nft add rule inet shellcrash $1 tcp dport {"$mix_port, $redir_port, $tproxy_port"} return
#过滤常用端口
[ -n "$PORTS" ] && {
- nft add rule inet shellcrash $1 ip daddr != {28.0.0.0/8} tcp dport != {$PORTS} return
- nft add rule inet shellcrash $1 ip daddr != {28.0.0.0/8} udp dport != {$PORTS} return
+ nft add rule inet shellcrash $1 ip daddr != {198.18.0.0/15} tcp dport != {$PORTS} return
+ nft add rule inet shellcrash $1 ip daddr != {198.18.0.0/15} udp dport != {$PORTS} return
nft add rule inet shellcrash $1 ip6 daddr != {fc00::/16} tcp dport != {$PORTS} return
- nft add rule inet shellcrash $1 ip6 daddr != {fc00::/16} udp dport != {$PORTS} return
+ nft add rule inet shellcrash $1 ip6 daddr != {fc00::/16} udp dport != {$PORTS} return
}
- #nft add rule inet shellcrash $1 ip saddr 28.0.0.0/8 return
+ #nft add rule inet shellcrash $1 ip saddr 198.18.0.0/15 return
nft add rule inet shellcrash $1 ip daddr {$RESERVED_IP} return #过滤保留地址
#过滤局域网设备
[ "$1" = 'prerouting' ] && {
@@ -76,27 +76,27 @@ start_nft_route() { #nftables-route通用工具
[ "$dns_mod" != "fake-ip" -a "$cn_ip_route" = "ON" -a -f "$BINDIR"/cn_ip.txt ] && {
CN_IP=$(awk '{printf "%s, ",$1}' "$BINDIR"/cn_ip.txt)
[ -n "$CN_IP" ] && {
- nft add set inet shellcrash cn_ip { type ipv4_addr \; flags interval \; }
- nft add element inet shellcrash cn_ip { $CN_IP }
- nft add rule inet shellcrash $1 ip daddr @cn_ip return
- }
- }
+ nft add set inet shellcrash cn_ip { type ipv4_addr \; flags interval \; }
+ nft add element inet shellcrash cn_ip { $CN_IP }
+ nft add rule inet shellcrash $1 ip daddr @cn_ip return
+ }
+ }
#局域网ipv6支持
if [ "$ipv6_redir" = "ON" -a "$1" = 'prerouting' -a "$firewall_area" != 5 ]; then
- HOST_IP6=$(echo $host_ipv6 | sed 's/[[:space:]]\+/, /g')
+ HOST_IP6=$(echo $host_ipv6 | sed 's/[[:space:]]\+/, /g')
add_ip6_route "$1"
elif [ "$ipv6_redir" = "ON" -a "$1" = 'output' -a \( "$firewall_area" = 2 -o "$firewall_area" = 3 \) ]; then
HOST_IP6="::1, $(echo $host_ipv6 | sed 's/[[:space:]]\+/, /g')"
- add_ip6_route "$1"
+ add_ip6_route "$1"
else
nft add rule inet shellcrash $1 meta nfproto ipv6 return
fi
- #屏蔽quic
- [ "$quic_rj" = 'ON' -a "$lan_proxy" = true ] && nft add rule inet shellcrash $1 udp dport {443, 8443} return
+ #屏蔽quic
+ [ "$quic_rj" = 'ON' -a "$lan_proxy" = true ] && nft add rule inet shellcrash $1 udp dport {443, 8443} return
#添加通用路由
nft add rule inet shellcrash "$1" "$JUMP"
#处理特殊路由
- [ "$redir_mod" = "混合模式" ] && {
+ [ "$redir_mod" = "Mix" ] && {
nft add rule inet shellcrash $1 meta l4proto tcp mark set $((fwmark + 1))
nft add chain inet shellcrash "$1"_mixtcp { type nat hook $2 priority -100 \; }
nft add rule inet shellcrash "$1"_mixtcp mark $((fwmark + 1)) meta l4proto tcp redirect to $redir_port
@@ -104,10 +104,10 @@ start_nft_route() { #nftables-route通用工具
#nft add rule inet shellcrash local_tproxy log prefix \"pre\" level debug
}
start_nft_dns() { #nftables-dns
- [ "$1" = 'prerouting' ] && {
- HOST_IP=$(echo $host_ipv4 | sed 's/[[:space:]]\+/, /g')
- HOST_IP6=$(echo $host_ipv6 | sed 's/[[:space:]]\+/, /g')
- }
+ [ "$1" = 'prerouting' ] && {
+ HOST_IP=$(echo $host_ipv4 | sed 's/[[:space:]]\+/, /g')
+ HOST_IP6=$(echo $host_ipv6 | sed 's/[[:space:]]\+/, /g')
+ }
[ "$1" = 'output' ] && HOST_IP="127.0.0.0/8, $(echo $local_ipv4 | sed 's/[[:space:]]\+/, /g')"
[ "$1" = 'prerouting_vm' ] && HOST_IP="$(echo $vm_ipv4 | sed 's/[[:space:]]\+/, /g')"
nft add chain inet shellcrash "$1"_dns { type nat hook $2 priority -100 \; }
@@ -133,26 +133,26 @@ start_nft_dns() { #nftables-dns
nft add rule inet shellcrash "$1"_dns tcp dport 53 redirect to "$dns_redir_port"
}
start_nft_wan() { #nftables公网防火墙
- HOST_IP=$(echo $host_ipv4 | sed 's/[[:space:]]\+/, /g')
- HOST_IP6=$(echo $host_ipv6 | sed 's/[[:space:]]\+/, /g')
+ HOST_IP=$(echo $host_ipv4 | sed 's/[[:space:]]\+/, /g')
+ HOST_IP6=$(echo $host_ipv6 | sed 's/[[:space:]]\+/, /g')
nft add chain inet shellcrash input { type filter hook input priority -100 \; }
nft add rule inet shellcrash input iif lo accept #本机请求全放行
- #端口放行
- [ -f "$CRASHDIR"/configs/gateway.cfg ] && . "$CRASHDIR"/configs/gateway.cfg
- accept_ports=$(echo "$fw_wan_ports,$vms_port,$sss_port" | sed "s/,,/,/g ;s/^,// ;s/,$// ;s/,/, /")
+ #端口放行
+ [ -f "$CRASHDIR"/configs/gateway.cfg ] && . "$CRASHDIR"/configs/gateway.cfg
+ accept_ports=$(echo "$fw_wan_ports,$vms_port,$sss_port" | sed "s/,,/,/g ;s/^,// ;s/,$// ;s/,/, /")
[ -n "$accept_ports" ] && {
- fw_wan_nfports="{ $(echo "$accept_ports" | sed 's/,/, /g') }"
- nft add rule inet shellcrash input tcp dport $fw_wan_nfports meta mark set 0x67890 accept
- nft add rule inet shellcrash input udp dport $fw_wan_nfports meta mark set 0x67890 accept
- }
- #端口拦截
- reject_ports="{ $mix_port, $db_port }"
- nft add rule inet shellcrash input ip saddr {$HOST_IP} accept
- nft add rule inet shellcrash input ip6 saddr {$HOST_IP6} accept
- nft add rule inet shellcrash input tcp dport $reject_ports reject
- nft add rule inet shellcrash input udp dport $reject_ports reject
- #fw4特殊处理
- nft list chain inet fw4 input >/dev/null 2>&1 && \
+ fw_wan_nfports="{ $(echo "$accept_ports" | sed 's/,/, /g') }"
+ nft add rule inet shellcrash input tcp dport $fw_wan_nfports meta mark set 0x67890 accept
+ nft add rule inet shellcrash input udp dport $fw_wan_nfports meta mark set 0x67890 accept
+ }
+ #端口拦截
+ reject_ports="{ $mix_port, $db_port }"
+ nft add rule inet shellcrash input ip saddr {$HOST_IP} accept
+ nft add rule inet shellcrash input ip6 saddr {$HOST_IP6} accept
+ nft add rule inet shellcrash input tcp dport $reject_ports reject
+ nft add rule inet shellcrash input udp dport $reject_ports reject
+ #fw4特殊处理
+ nft list chain inet fw4 input >/dev/null 2>&1 && \
nft list chain inet fw4 input | grep -q '67890' || \
nft insert rule inet fw4 input meta mark 0x67890 accept 2>/dev/null
}
@@ -168,12 +168,12 @@ start_nftables() { #nftables配置总入口
[ "$local_proxy" = true ] && start_nft_dns output output #本机dns转发
}
#分模式设置流量劫持
- [ "$redir_mod" = "Redir模式" ] && {
+ [ "$redir_mod" = "Redir" ] && {
JUMP="meta l4proto tcp redirect to $redir_port" #跳转劫持的具体命令
[ "$lan_proxy" = true ] && start_nft_route prerouting prerouting nat -100
[ "$local_proxy" = true ] && start_nft_route output output nat -100
}
- [ "$redir_mod" = "Tproxy模式" ] && (modprobe nft_tproxy >/dev/null 2>&1 || lsmod 2>/dev/null | grep -q nft_tproxy) && {
+ [ "$redir_mod" = "Tproxy" ] && (modprobe nft_tproxy >/dev/null 2>&1 || lsmod 2>/dev/null | grep -q nft_tproxy) && {
JUMP="meta l4proto {tcp, udp} mark set $fwmark tproxy to :$tproxy_port" #跳转劫持的具体命令
[ "$lan_proxy" = true ] && start_nft_route prerouting prerouting filter -150
[ "$local_proxy" = true ] && {
@@ -184,8 +184,8 @@ start_nftables() { #nftables配置总入口
}
}
[ "$tun_statu" = true ] && {
- [ "$redir_mod" = "Tun模式" ] && JUMP="meta l4proto {tcp, udp} mark set $fwmark" #跳转劫持的具体命令
- [ "$redir_mod" = "混合模式" ] && JUMP="meta l4proto udp mark set $fwmark" #跳转劫持的具体命令
+ [ "$redir_mod" = "Tun" ] && JUMP="meta l4proto {tcp, udp} mark set $fwmark" #跳转劫持的具体命令
+ [ "$redir_mod" = "Mix" ] && JUMP="meta l4proto udp mark set $fwmark" #跳转劫持的具体命令
[ "$lan_proxy" = true ] && {
start_nft_route prerouting prerouting filter -150
#放行流量
diff --git a/scripts/starts/fw_start.sh b/scripts/starts/fw_start.sh
index f0ae831f..955692d7 100644
--- a/scripts/starts/fw_start.sh
+++ b/scripts/starts/fw_start.sh
@@ -8,33 +8,33 @@
[ -z "$common_ports" ] && common_ports='ON'
[ -z "$multiport" ] && multiport='22,80,443,8080,8443'
[ "$common_ports" = "ON" ] && ports="-m multiport --dports $multiport"
-[ -z "$redir_mod" ] && [ "$USER" = "root" -o "$USER" = "admin" ] && redir_mod='Redir模式'
+[ -z "$redir_mod" ] && [ "$USER" = "root" -o "$USER" = "admin" ] && redir_mod='Redir'
[ -z "$dns_mod" ] && dns_mod='redir_host'
[ -z "$redir_mod" ] && firewall_area='4'
#设置策略路由
[ "$firewall_area" != 4 ] && {
- [ "$redir_mod" = "Tproxy模式" ] && ip route add local default dev lo table $table 2>/dev/null
- [ "$redir_mod" = "Tun模式" -o "$redir_mod" = "混合模式" ] && {
- i=1
- while [ -z "$(ip route list | grep utun)" -a "$i" -le 29 ]; do
- sleep 1
- i=$((i + 1))
- done
- if [ -z "$(ip route list | grep utun)" ]; then
- logger "找不到tun模块,放弃启动tun相关防火墙规则!" 31
- else
- ip route add default dev utun table $table && tun_statu=true
- fi
- }
- [ "$firewall_area" = 5 ] && ip route add default via $bypass_host table $table 2>/dev/null
- [ "$redir_mod" != "Redir模式" ] && ip rule add fwmark $fwmark table $table 2>/dev/null
+ [ "$redir_mod" = "Tproxy" ] && ip route add local default dev lo table $table 2>/dev/null
+ [ "$redir_mod" = "Tun" -o "$redir_mod" = "Mix" ] && {
+ i=1
+ while [ -z "$(ip route list | grep utun)" -a "$i" -le 29 ]; do
+ sleep 1
+ i=$((i + 1))
+ done
+ if [ -z "$(ip route list | grep utun)" ]; then
+ logger "找不到tun模块,放弃启动tun相关防火墙规则!" 31
+ else
+ ip route add default dev utun table $table && tun_statu=true
+ fi
+ }
+ [ "$firewall_area" = 5 ] && ip route add default via $bypass_host table $table 2>/dev/null
+ [ "$redir_mod" != "Redir" ] && ip rule add fwmark $fwmark table $table 2>/dev/null
}
#添加ipv6路由
[ "$ipv6_redir" = "ON" -a "$firewall_area" -le 3 ] && {
- [ "$redir_mod" = "Tproxy模式" ] && ip -6 route add local default dev lo table $((table + 1)) 2>/dev/null
- [ -n "$(ip route list | grep utun)" ] && ip -6 route add default dev utun table $((table + 1)) 2>/dev/null
- [ "$redir_mod" != "Redir模式" ] && ip -6 rule add fwmark $fwmark table $((table + 1)) 2>/dev/null
+ [ "$redir_mod" = "Tproxy" ] && ip -6 route add local default dev lo table $((table + 1)) 2>/dev/null
+ [ -n "$(ip route list | grep utun)" ] && ip -6 route add default dev utun table $((table + 1)) 2>/dev/null
+ [ "$redir_mod" != "Redir" ] && ip -6 rule add fwmark $fwmark table $((table + 1)) 2>/dev/null
}
#判断代理用途
[ "$firewall_area" = 2 -o "$firewall_area" = 3 ] && local_proxy=true
@@ -44,11 +44,11 @@
[ "$firewall_mod" = 'nftables' ] && . "$CRASHDIR"/starts/fw_nftables.sh && start_nftables
#修复部分虚拟机dns查询失败的问题
[ "$firewall_area" = 2 -o "$firewall_area" = 3 ] && [ -z "$(grep '127.0.0.1' /etc/resolv.conf 2>/dev/null)" ] && [ "$systype" != 'container' ] && {
- line=$(grep -n 'nameserver' /etc/resolv.conf | awk -F: 'FNR==1{print $1}')
- sed -i "$line i\nameserver 127.0.0.1 #shellcrash-dns-repair" /etc/resolv.conf >/dev/null 2>&1
+ line=$(grep -n 'nameserver' /etc/resolv.conf | awk -F: 'FNR==1{print $1}')
+ sed -i "$line i\nameserver 127.0.0.1 #shellcrash-dns-repair" /etc/resolv.conf >/dev/null 2>&1
}
#移除openwrt-dnsmasq的DNS重定向
[ "$(uci get dhcp.@dnsmasq[0].dns_redirect 2>/dev/null)" = 1 ] && {
- uci del dhcp.@dnsmasq[0].dns_redirect
- uci commit dhcp.@dnsmasq[0]
+ uci del dhcp.@dnsmasq[0].dns_redirect
+ uci commit dhcp.@dnsmasq[0]
}
diff --git a/scripts/starts/fw_stop.sh b/scripts/starts/fw_stop.sh
index d528b7be..2a5d99c6 100644
--- a/scripts/starts/fw_stop.sh
+++ b/scripts/starts/fw_stop.sh
@@ -14,110 +14,149 @@
accept_ports=$(echo "$fw_wan_ports,$vms_port,$sss_port" | sed "s/,,/,/g ;s/^,// ;s/,$//")
#重置iptables相关规则
ckcmd iptables && {
- ckcmd iptables && iptables -h | grep -q '\-w' && iptable='iptables -w' || iptable=iptables
- #dns
- $iptable -t nat -D PREROUTING -p tcp --dport 53 -j shellcrash_dns 2>/dev/null
- $iptable -t nat -D PREROUTING -p udp --dport 53 -j shellcrash_dns 2>/dev/null
- $iptable -t nat -D OUTPUT -p udp --dport 53 -j shellcrash_dns_out 2>/dev/null
- $iptable -t nat -D OUTPUT -p tcp --dport 53 -j shellcrash_dns_out 2>/dev/null
- #redir
- $iptable -t nat -D PREROUTING -p tcp $ports -j shellcrash 2>/dev/null
- $iptable -t nat -D PREROUTING -p tcp -d 28.0.0.0/8 -j shellcrash 2>/dev/null
- $iptable -t nat -D OUTPUT -p tcp $ports -j shellcrash_out 2>/dev/null
- $iptable -t nat -D OUTPUT -p tcp -d 28.0.0.0/8 -j shellcrash_out 2>/dev/null
- #vm_dns
- $iptable -t nat -D PREROUTING -p tcp --dport 53 -j shellcrash_vm_dns 2>/dev/null
- $iptable -t nat -D PREROUTING -p udp --dport 53 -j shellcrash_vm_dns 2>/dev/null
- #vm_redir
- $iptable -t nat -D PREROUTING -p tcp $ports -j shellcrash_vm 2>/dev/null
- $iptable -t nat -D PREROUTING -p tcp -d 28.0.0.0/8 -j shellcrash_vm 2>/dev/null
- #TPROXY&tun
- $iptable -t mangle -D PREROUTING -p tcp $ports -j shellcrash_mark 2>/dev/null
- $iptable -t mangle -D PREROUTING -p udp $ports -j shellcrash_mark 2>/dev/null
- $iptable -t mangle -D PREROUTING -p tcp -d 28.0.0.0/8 -j shellcrash_mark 2>/dev/null
- $iptable -t mangle -D PREROUTING -p udp -d 28.0.0.0/8 -j shellcrash_mark 2>/dev/null
- $iptable -t mangle -D OUTPUT -p tcp $ports -j shellcrash_mark_out 2>/dev/null
- $iptable -t mangle -D OUTPUT -p udp $ports -j shellcrash_mark_out 2>/dev/null
- $iptable -t mangle -D OUTPUT -p tcp -d 28.0.0.0/8 -j shellcrash_mark_out 2>/dev/null
- $iptable -t mangle -D OUTPUT -p udp -d 28.0.0.0/8 -j shellcrash_mark_out 2>/dev/null
- $iptable -t mangle -D PREROUTING -m mark --mark $fwmark -p tcp -j TPROXY --on-port $tproxy_port 2>/dev/null
- $iptable -t mangle -D PREROUTING -m mark --mark $fwmark -p udp -j TPROXY --on-port $tproxy_port 2>/dev/null
- #tun
- $iptable -D FORWARD -o utun -j ACCEPT 2>/dev/null
- #屏蔽QUIC
- [ "$dns_mod" != "fake-ip" ] && [ "$cn_ip_route" != "OFF" ] && set_cn_ip='-m set ! --match-set cn_ip dst'
- $iptable -D INPUT -p udp --dport 443 $set_cn_ip -j REJECT 2>/dev/null
- $iptable -D FORWARD -p udp --dport 443 -o utun $set_cn_ip -j REJECT 2>/dev/null
- #公网访问
- $iptable -D INPUT -i lo -j ACCEPT 2>/dev/null
- for ip in $host_ipv4; do
- $iptable -D INPUT -s $ip -j ACCEPT 2>/dev/null
- done
- $iptable -D INPUT -p tcp -m multiport --dports "$accept_ports" -j ACCEPT 2>/dev/null
- $iptable -D INPUT -p udp -m multiport --dports "$accept_ports" -j ACCEPT 2>/dev/null
- $iptable -D INPUT -p tcp -m multiport --dports "$mix_port,$db_port" -j REJECT 2>/dev/null
- $iptable -D INPUT -p udp -m multiport --dports "$mix_port,$db_port" -j REJECT 2>/dev/null
- #清理shellcrash自建表
- for text in shellcrash_dns shellcrash shellcrash_out shellcrash_dns_out shellcrash_vm shellcrash_vm_dns; do
- $iptable -t nat -F "$text" 2>/dev/null
- $iptable -t nat -X "$text" 2>/dev/null
- done
- for text in shellcrash_mark shellcrash_mark_out; do
- $iptable -t mangle -F "$text" 2>/dev/null
- $iptable -t mangle -X "$text" 2>/dev/null
- done
+ ckcmd iptables && iptables -h | grep -q '\-w' && iptable='iptables -w' || iptable=iptables
+ #dns
+ $iptable -t nat -D PREROUTING -p tcp --dport 53 -j shellcrash_dns 2>/dev/null
+ $iptable -t nat -D PREROUTING -p udp --dport 53 -j shellcrash_dns 2>/dev/null
+ $iptable -t nat -D OUTPUT -p udp --dport 53 -j shellcrash_dns_out 2>/dev/null
+ $iptable -t nat -D OUTPUT -p tcp --dport 53 -j shellcrash_dns_out 2>/dev/null
+ if [ -n "$ports" ]; then
+ clean_ports=$(echo "$multiport" | sed 's/ //g')
+ echo "$clean_ports" | awk -F, '{
+ for(i=1; i<=NF; i+=9) {
+ group=""; for(j=i; j/dev/null
+ $iptable -t nat -D OUTPUT -p tcp -m multiport --dports "$port_group" -j shellcrash_out 2>/dev/null
+ $iptable -t nat -D PREROUTING -p tcp -m multiport --dports "$port_group" -j shellcrash_vm 2>/dev/null
+ $iptable -t mangle -D PREROUTING -p tcp -m multiport --dports "$port_group" -j shellcrash_mark 2>/dev/null
+ $iptable -t mangle -D PREROUTING -p udp -m multiport --dports "$port_group" -j shellcrash_mark 2>/dev/null
+ $iptable -t mangle -D OUTPUT -p tcp -m multiport --dports "$port_group" -j shellcrash_mark_out 2>/dev/null
+ $iptable -t mangle -D OUTPUT -p udp -m multiport --dports "$port_group" -j shellcrash_mark_out 2>/dev/null
+ fi
+ done
+ else
+ $iptable -t nat -D PREROUTING -p tcp -j shellcrash 2>/dev/null
+ $iptable -t nat -D OUTPUT -p tcp -j shellcrash_out 2>/dev/null
+ $iptable -t nat -D PREROUTING -p tcp -j shellcrash_vm 2>/dev/null
+ $iptable -t mangle -D PREROUTING -p tcp -j shellcrash_mark 2>/dev/null
+ $iptable -t mangle -D PREROUTING -p udp -j shellcrash_mark 2>/dev/null
+ $iptable -t mangle -D OUTPUT -p tcp -j shellcrash_mark_out 2>/dev/null
+ $iptable -t mangle -D OUTPUT -p udp -j shellcrash_mark_out 2>/dev/null
+ fi
+ #redir
+ $iptable -t nat -D PREROUTING -p tcp -d 198.18.0.0/15 -j shellcrash 2>/dev/null
+ $iptable -t nat -D OUTPUT -p tcp -d 198.18.0.0/15 -j shellcrash_out 2>/dev/null
+ #vm_dns
+ $iptable -t nat -D PREROUTING -p tcp --dport 53 -j shellcrash_vm_dns 2>/dev/null
+ $iptable -t nat -D PREROUTING -p udp --dport 53 -j shellcrash_vm_dns 2>/dev/null
+ #vm_redir
+ $iptable -t nat -D PREROUTING -p tcp -d 198.18.0.0/15 -j shellcrash_vm 2>/dev/null
+ #TPROXY&tun
+ $iptable -t mangle -D PREROUTING -p tcp -d 198.18.0.0/15 -j shellcrash_mark 2>/dev/null
+ $iptable -t mangle -D PREROUTING -p udp -d 198.18.0.0/15 -j shellcrash_mark 2>/dev/null
+ $iptable -t mangle -D OUTPUT -p tcp -d 198.18.0.0/15 -j shellcrash_mark_out 2>/dev/null
+ $iptable -t mangle -D OUTPUT -p udp -d 198.18.0.0/15 -j shellcrash_mark_out 2>/dev/null
+ $iptable -t mangle -D PREROUTING -m mark --mark $fwmark -p tcp -j TPROXY --on-port $tproxy_port 2>/dev/null
+ $iptable -t mangle -D PREROUTING -m mark --mark $fwmark -p udp -j TPROXY --on-port $tproxy_port 2>/dev/null
+ #tun
+ $iptable -D FORWARD -o utun -j ACCEPT 2>/dev/null
+ #屏蔽QUIC
+ [ "$dns_mod" != "fake-ip" ] && [ "$cn_ip_route" != "OFF" ] && set_cn_ip='-m set ! --match-set cn_ip dst'
+ $iptable -D INPUT -p udp --dport 443 $set_cn_ip -j REJECT 2>/dev/null
+ $iptable -D FORWARD -p udp --dport 443 -o utun $set_cn_ip -j REJECT 2>/dev/null
+ #公网访问
+ $iptable -D INPUT -i lo -j ACCEPT 2>/dev/null
+ for ip in $host_ipv4; do
+ $iptable -D INPUT -s $ip -j ACCEPT 2>/dev/null
+ done
+ $iptable -D INPUT -p tcp -m multiport --dports "$accept_ports" -j ACCEPT 2>/dev/null
+ $iptable -D INPUT -p udp -m multiport --dports "$accept_ports" -j ACCEPT 2>/dev/null
+ $iptable -D INPUT -p tcp -m multiport --dports "$mix_port,$db_port" -j REJECT 2>/dev/null
+ $iptable -D INPUT -p udp -m multiport --dports "$mix_port,$db_port" -j REJECT 2>/dev/null
+ #清理shellcrash自建表
+ for text in shellcrash_dns shellcrash shellcrash_out shellcrash_dns_out shellcrash_vm shellcrash_vm_dns; do
+ $iptable -t nat -F "$text" 2>/dev/null
+ $iptable -t nat -X "$text" 2>/dev/null
+ done
+ for text in shellcrash_mark shellcrash_mark_out; do
+ $iptable -t mangle -F "$text" 2>/dev/null
+ $iptable -t mangle -X "$text" 2>/dev/null
+ done
}
#重置ipv6规则
ckcmd ip6tables && {
- ckcmd ip6tables && ip6tables -h | grep -q '\-w' && ip6table='ip6tables -w' || ip6table=ip6tables
- #dns
- $ip6table -t nat -D PREROUTING -p tcp --dport 53 -j shellcrashv6_dns 2>/dev/null
- $ip6table -t nat -D PREROUTING -p udp --dport 53 -j shellcrashv6_dns 2>/dev/null
- #redir
- $ip6table -t nat -D PREROUTING -p tcp $ports -j shellcrashv6 2>/dev/null
- $ip6table -t nat -D PREROUTING -p tcp -d fc00::/16 -j shellcrashv6 2>/dev/null
- $ip6table -t nat -D OUTPUT -p tcp $ports -j shellcrashv6_out 2>/dev/null
- $ip6table -t nat -D OUTPUT -p tcp -d fc00::/16 -j shellcrashv6_out 2>/dev/null
- $ip6table -D INPUT -p tcp --dport 53 -j REJECT 2>/dev/null
- $ip6table -D INPUT -p udp --dport 53 -j REJECT 2>/dev/null
- #mark
- $ip6table -t mangle -D PREROUTING -p tcp $ports -j shellcrashv6_mark 2>/dev/null
- $ip6table -t mangle -D PREROUTING -p udp $ports -j shellcrashv6_mark 2>/dev/null
- $ip6table -t mangle -D PREROUTING -p tcp -d fc00::/16 -j shellcrashv6_mark 2>/dev/null
- $ip6table -t mangle -D PREROUTING -p udp -d fc00::/16 -j shellcrashv6_mark 2>/dev/null
- $ip6table -t mangle -D OUTPUT -p tcp $ports -j shellcrashv6_mark_out 2>/dev/null
- $ip6table -t mangle -D OUTPUT -p udp $ports -j shellcrashv6_mark_out 2>/dev/null
- $ip6table -t mangle -D OUTPUT -p tcp -d fc00::/16 -j shellcrashv6_mark_out 2>/dev/null
- $ip6table -t mangle -D OUTPUT -p udp -d fc00::/16 -j shellcrashv6_mark_out 2>/dev/null
- $ip6table -D INPUT -p udp --dport 443 $set_cn_ip -j REJECT 2>/dev/null
- $ip6table -t mangle -D PREROUTING -m mark --mark $fwmark -p tcp -j TPROXY --on-port $tproxy_port 2>/dev/null
- $ip6table -t mangle -D PREROUTING -m mark --mark $fwmark -p udp -j TPROXY --on-port $tproxy_port 2>/dev/null
- #tun
- $ip6table -D FORWARD -o utun -j ACCEPT 2>/dev/null
- #屏蔽QUIC
- [ "$dns_mod" != "fake-ip" ] && [ "$cn_ip_route" != "OFF" ] && set_cn_ip6='-m set ! --match-set cn_ip6 dst'
- $ip6table -D INPUT -p udp --dport 443 $set_cn_ip6 -j REJECT 2>/dev/null
- $ip6table -D FORWARD -p udp --dport 443 -o utun $set_cn_ip6 -j REJECT 2>/dev/null
- #公网访问
- $ip6table -D INPUT -i lo -j ACCEPT 2>/dev/null
- for ip in $host_ipv6; do
- $ip6table -D INPUT -s $ip -j ACCEPT 2>/dev/null
- done
- $ip6table -D INPUT -p tcp -m multiport --dports "$accept_ports" -j ACCEPT 2>/dev/null
- $ip6table -D INPUT -p udp -m multiport --dports "$accept_ports" -j ACCEPT 2>/dev/null
- $ip6table -D INPUT -p tcp -m multiport --dports "$mix_port,$db_port" -j REJECT 2>/dev/null
- $ip6table -D INPUT -p udp -m multiport --dports "$mix_port,$db_port" -j REJECT 2>/dev/null
- #清理shellcrash自建表
- for text in shellcrashv6_dns shellcrashv6 shellcrashv6_out; do
- $ip6table -t nat -F "$text" 2>/dev/null
- $ip6table -t nat -X "$text" 2>/dev/null
- done
- for text in shellcrashv6_mark shellcrashv6_mark_out; do
- $ip6table -t mangle -F "$text" 2>/dev/null
- $ip6table -t mangle -X "$text" 2>/dev/null
- done
- $ip6table -t mangle -F shellcrashv6_mark 2>/dev/null
- $ip6table -t mangle -X shellcrashv6_mark 2>/dev/null
+ ckcmd ip6tables && ip6tables -h | grep -q '\-w' && ip6table='ip6tables -w' || ip6table=ip6tables
+ #dns
+ $ip6table -t nat -D PREROUTING -p tcp --dport 53 -j shellcrashv6_dns 2>/dev/null
+ $ip6table -t nat -D PREROUTING -p udp --dport 53 -j shellcrashv6_dns 2>/dev/null
+ if [ -n "$ports" ]; then
+ clean_ports=$(echo "$multiport" | sed 's/ //g')
+ echo "$clean_ports" | awk -F, '{
+ for(i=1; i<=NF; i+=9) {
+ group=""; for(j=i; j/dev/null
+ $ip6table -t nat -D OUTPUT -p tcp -m multiport --dports "$port_group" -j shellcrashv6_out 2>/dev/null
+ $ip6table -t mangle -D PREROUTING -p tcp -m multiport --dports "$port_group" -j shellcrashv6_mark 2>/dev/null
+ $ip6table -t mangle -D PREROUTING -p udp -m multiport --dports "$port_group" -j shellcrashv6_mark 2>/dev/null
+ $ip6table -t mangle -D OUTPUT -p tcp -m multiport --dports "$port_group" -j shellcrashv6_mark_out 2>/dev/null
+ $ip6table -t mangle -D OUTPUT -p udp -m multiport --dports "$port_group" -j shellcrashv6_mark_out 2>/dev/null
+ fi
+ done
+ else
+ $ip6table -t nat -D PREROUTING -p tcp -j shellcrashv6 2>/dev/null
+ $ip6table -t nat -D OUTPUT -p tcp -j shellcrashv6_out 2>/dev/null
+ $ip6table -t mangle -D PREROUTING -p tcp -j shellcrashv6_mark 2>/dev/null
+ $ip6table -t mangle -D PREROUTING -p udp -j shellcrashv6_mark 2>/dev/null
+ $ip6table -t mangle -D OUTPUT -p tcp -j shellcrashv6_mark_out 2>/dev/null
+ $ip6table -t mangle -D OUTPUT -p udp -j shellcrashv6_mark_out 2>/dev/null
+ fi
+ #redir
+ $ip6table -t nat -D PREROUTING -p tcp -d fc00::/16 -j shellcrashv6 2>/dev/null
+ $ip6table -t nat -D OUTPUT -p tcp -d fc00::/16 -j shellcrashv6_out 2>/dev/null
+ $ip6table -D INPUT -p tcp --dport 53 -j REJECT 2>/dev/null
+ $ip6table -D INPUT -p udp --dport 53 -j REJECT 2>/dev/null
+ #mark
+ $ip6table -t mangle -D PREROUTING -p tcp -d fc00::/16 -j shellcrashv6_mark 2>/dev/null
+ $ip6table -t mangle -D PREROUTING -p udp -d fc00::/16 -j shellcrashv6_mark 2>/dev/null
+ $ip6table -t mangle -D OUTPUT -p tcp -d fc00::/16 -j shellcrashv6_mark_out 2>/dev/null
+ $ip6table -t mangle -D OUTPUT -p udp -d fc00::/16 -j shellcrashv6_mark_out 2>/dev/null
+ $ip6table -D INPUT -p udp --dport 443 $set_cn_ip -j REJECT 2>/dev/null
+ $ip6table -t mangle -D PREROUTING -m mark --mark $fwmark -p tcp -j TPROXY --on-port $tproxy_port 2>/dev/null
+ $ip6table -t mangle -D PREROUTING -m mark --mark $fwmark -p udp -j TPROXY --on-port $tproxy_port 2>/dev/null
+ #tun
+ $ip6table -D FORWARD -o utun -j ACCEPT 2>/dev/null
+ #屏蔽QUIC
+ [ "$dns_mod" != "fake-ip" ] && [ "$cn_ip_route" != "OFF" ] && set_cn_ip6='-m set ! --match-set cn_ip6 dst'
+ $ip6table -D INPUT -p udp --dport 443 $set_cn_ip6 -j REJECT 2>/dev/null
+ $ip6table -D FORWARD -p udp --dport 443 -o utun $set_cn_ip6 -j REJECT 2>/dev/null
+ #公网访问
+ $ip6table -D INPUT -i lo -j ACCEPT 2>/dev/null
+ for ip in $host_ipv6; do
+ $ip6table -D INPUT -s $ip -j ACCEPT 2>/dev/null
+ done
+ $ip6table -D INPUT -p tcp -m multiport --dports "$accept_ports" -j ACCEPT 2>/dev/null
+ $ip6table -D INPUT -p udp -m multiport --dports "$accept_ports" -j ACCEPT 2>/dev/null
+ $ip6table -D INPUT -p tcp -m multiport --dports "$mix_port,$db_port" -j REJECT 2>/dev/null
+ $ip6table -D INPUT -p udp -m multiport --dports "$mix_port,$db_port" -j REJECT 2>/dev/null
+ #清理shellcrash自建表
+ for text in shellcrashv6_dns shellcrashv6 shellcrashv6_out; do
+ $ip6table -t nat -F "$text" 2>/dev/null
+ $ip6table -t nat -X "$text" 2>/dev/null
+ done
+ for text in shellcrashv6_mark shellcrashv6_mark_out; do
+ $ip6table -t mangle -F "$text" 2>/dev/null
+ $ip6table -t mangle -X "$text" 2>/dev/null
+ done
+ $ip6table -t mangle -F shellcrashv6_mark 2>/dev/null
+ $ip6table -t mangle -X shellcrashv6_mark 2>/dev/null
}
#清理ipset规则
ipset destroy cn_ip >/dev/null 2>&1
diff --git a/scripts/starts/general_init.sh b/scripts/starts/general_init.sh
index 8a8bcde4..ddb5e1d1 100644
--- a/scripts/starts/general_init.sh
+++ b/scripts/starts/general_init.sh
@@ -3,28 +3,30 @@
#初始化目录
[ -z "$CRASHDIR" ] && CRASHDIR=$( cd $(dirname $0);cd ..;pwd)
+TASKCFGDIR="$CRASHDIR"/configs/task
profile=/etc/profile
. "$CRASHDIR"/libs/set_profile.sh
. "$CRASHDIR"/libs/set_cron.sh
. "$CRASHDIR"/configs/ShellCrash.cfg
#padavan和华硕环境变量目录设置
if [ -d "/etc/storage/clash" -o -d "/etc/storage/ShellCrash" ]; then
- i=1
- while [ ! -w /etc/profile -a "$i" -lt 10 ]; do
- sleep 3 && i=$((i + 1))
- done
- [ -w "$profile" ] || profile=/etc_ro/profile
- [ "$zip_type" = 'upx' ] || mount -t tmpfs -o remount,rw,size=45M tmpfs /tmp #增加/tmp空间以适配新的内核压缩方式
- sed -i '' "$profile" #将软链接转化为一般文件
+ i=1
+ while [ ! -w /etc/profile -a "$i" -lt 10 ]; do
+ sleep 3 && i=$((i + 1))
+ done
+ [ -w "$profile" ] || profile=/etc_ro/profile
+ [ "$zip_type" = 'upx' ] || mount -t tmpfs -o remount,rw,size=45M tmpfs /tmp #增加/tmp空间以适配新的内核压缩方式
+ sed -i '' "$profile" #将软链接转化为一般文件
elif [ -d "/jffs" ]; then
- sleep 60
- [ -w "$profile" ] || profile=$(cat /etc/profile | grep -oE '\-f.*jffs.*profile' | awk '{print $2}')
+ sleep 60
+ [ -w "$profile" ] || profile=$(cat /etc/profile | grep -oE '\-f.*jffs.*profile' | awk '{print $2}')
fi
#写入环境变量
set_profile "$profile"
#启动进程或删除守护进程
if [ -f "$CRASHDIR"/.dis_startup ] || [ -f "$CRASHDIR"/.start_error ];then
- cronset "保守模式守护进程"
+ cronset "保守模式守护进程"
else
- "$CRASHDIR"/start.sh start
+ echo 0 > /proc/sys/vm/overcommit_memory #优化系统默认内存检测机制
+ "$CRASHDIR"/start.sh start
fi
diff --git a/scripts/starts/singbox_check.sh b/scripts/starts/singbox_check.sh
index 9307664f..10bbf6f5 100644
--- a/scripts/starts/singbox_check.sh
+++ b/scripts/starts/singbox_check.sh
@@ -2,8 +2,8 @@
singbox_check() { #singbox启动前检查
#检测singboxr专属功能
[ "$crashcore" != "singboxr" ] && [ -n "$(cat "$CRASHDIR"/jsons/*.json | grep -oE '"shadowsocksr"|"providers"')" ] && {
- . "$CRASHDIR"/starts/core_exchange.sh && core_exchange singboxr 'singboxr内核专属功能'
- }
+ . "$CRASHDIR"/starts/core_exchange.sh && core_exchange singboxr 'singboxr内核专属功能'
+ }
check_core
#预下载cn.srs数据库
[ "$dns_mod" = "mix" ] || [ "$dns_mod" = "route" ] && ! grep -Eq '"tag" *:[[:space:]]*"cn"' "$CRASHDIR"/jsons/*.json && check_geo ruleset/cn.srs srs_geosite_cn.srs
diff --git a/scripts/starts/singbox_modify.sh b/scripts/starts/singbox_modify.sh
index 0ee8eeec..7e68080b 100644
--- a/scripts/starts/singbox_modify.sh
+++ b/scripts/starts/singbox_modify.sh
@@ -1,8 +1,9 @@
#!/bin/sh
# Copyright (C) Juewuy
- #修饰singbox配置文件
-parse_singbox_dns() { #dns转换
+#修饰singbox配置文件
+
+parse_singbox_dns() { #dns转换工具
first_dns=$(echo "$1" | cut -d',' -f1 | cut -d' ' -f1)
type=""
server=""
@@ -39,10 +40,10 @@ parse_singbox_dns() { #dns转换
esac
fi
# 输出
- echo '"type": "'"$type"'", "server": "'"$server"'", "server_port": '"$port"','
+ echo '"type": "'"$type"'", "server": "'"$server"'", "server_port": '"$port"','
}
-modify_json() {
- #提取配置文件以获得outbounds.json,providers.json及route.json
+
+extract_base_jsons() { #提取配置文件以获得outbounds.json,providers.json及route.json
"$TMPDIR"/CrashCore format -c $core_config >"$TMPDIR"/format.json
echo '{' >"$TMPDIR"/jsons/outbounds.json
echo '{' >"$TMPDIR"/jsons/route.json
@@ -52,12 +53,40 @@ modify_json() {
cat "$TMPDIR"/format.json | sed -n '/^ "providers":/,/^ "[a-z]/p' | sed '$d' >>"$TMPDIR"/jsons/providers.json
}
cat "$TMPDIR"/format.json | sed -n '/"route":/,/^\( "[a-z]\|}\)/p' | sed '$d' >>"$TMPDIR"/jsons/route.json
- #生成endpoints.json
- [ "$ts_service" = ON ] || [ "$wg_service" = ON ] && [ "$zip_type" != upx ] && {
- . "$CRASHDIR"/configs/gateway.cfg
- . "$CRASHDIR"/libs/sb_endpoints.sh
+ #清理PASS规则
+ sed -i 's/"PASS"/"DIRECT"/g' "$TMPDIR"/jsons/outbounds.json
+}
+
+generate_basic_jsons() {
+ #适配1.14+版本
+ if [ "$(printf '%s' "$core_v" | cut -d. -f2)" -lt 14 ];then
+ preferred='"ip_accept_any": true,'
+ detour_direct='"download_detour": "DIRECT"'
+ else
+ preferred='"preferred_by": [ "hosts" ],'
+ detour_direct='"http_client": "detour_direct"'
+ #生成http_clients.json
+ cat >"$TMPDIR"/jsons/http_clients.json <"$TMPDIR"/jsons/log.json <"$TMPDIR"/jsons/add_rule_set.json <"$TMPDIR"/jsons/add_route.json <"$TMPDIR"/jsons/certificate.json <>"$TMPDIR"/jsons/tun.json <"$TMPDIR"/jsons/add_outbounds.json <"$TMPDIR"/jsons/experimental.json </dev/null)" ] && {
cat "$CRASHDIR"/yamls/rules.yaml |
sed '/#.*/d' |
@@ -342,10 +398,13 @@ EOF
sed '$s/,$/ ] } }/' >"$TMPDIR"/jsons/cust_add_rules.json
[ ! -s "$TMPDIR"/jsons/cust_add_rules.json ] && rm -rf "$TMPDIR"/jsons/cust_add_rules.json
}
+}
+
+normalize_and_finalize_jsons() { #修饰文件
#清理route.json中的process_name规则以及"auto_detect_interface"
sed -i '/"process_name": \[/,/],$/d' "$TMPDIR"/jsons/route.json
sed -i '/"process_name": "[^"]*",/d' "$TMPDIR"/jsons/route.json
- sed -i 's/"auto_detect_interface": true/"auto_detect_interface": false/g' "$TMPDIR"/jsons/route.json
+ sed -i 's/"auto_detect_interface": true/"auto_detect_interface": false/g' "$TMPDIR"/jsons/route.json
#跳过本地tls证书验证
if [ "$skip_cert" != "OFF" ]; then
sed -i 's/"insecure": false/"insecure": true/' "$TMPDIR"/jsons/outbounds.json "$TMPDIR"/jsons/providers.json 2>/dev/null
@@ -361,10 +420,13 @@ EOF
rm -rf "$TMPDIR"/jsons/${file}.json
fi
done
+}
+
+link_custom_jsons() { #合并文件
#加载自定义配置文件
mkdir -p "$TMPDIR"/jsons_base
#以下为覆盖脚本的自定义文件
- for char in log dns ntp certificate experimental; do
+ for char in log dns ntp certificate http_clients experimental; do
[ -s "$CRASHDIR"/jsons/${char}.json ] && {
ln -sf "$CRASHDIR"/jsons/${char}.json "$TMPDIR"/jsons/cust_${char}.json
mv -f "$TMPDIR"/jsons/${char}.json "$TMPDIR"/jsons_base #如果重复则临时备份
@@ -376,7 +438,9 @@ EOF
ln -sf "$CRASHDIR"/jsons/${char}.json "$TMPDIR"/jsons/cust_${char}.json
}
done
- #测试自定义配置文件
+}
+
+test_json() { #测试自定义配置文件
if ! error=$("$TMPDIR"/CrashCore check -D "$BINDIR" -C "$TMPDIR"/jsons 2>&1); then
echo $error
error_file=$(echo $error | grep -Eo 'cust.*\.json' | sed 's/cust_//g')
@@ -387,6 +451,21 @@ EOF
rm -rf "$TMPDIR"/jsons/cust_*
mv -f "$TMPDIR"/jsons_base/* "$TMPDIR"/jsons 2>/dev/null
fi
+}
+
+modify_json() { #入口
+ extract_base_jsons
+ generate_basic_jsons
+ gen_dns
+ gen_outbounds
+ gen_certificate
+ gen_inbounds
+ add_outbounds
+ gen_experimental
+ generate_custom_rules_json
+ normalize_and_finalize_jsons
+ link_custom_jsons
+ test_json
#清理缓存
rm -rf "$TMPDIR"/*.json
rm -rf "$TMPDIR"/jsons_base
diff --git a/scripts/starts/snapshot_init.sh b/scripts/starts/snapshot_init.sh
index b21107bd..9445b7cf 100644
--- a/scripts/starts/snapshot_init.sh
+++ b/scripts/starts/snapshot_init.sh
@@ -8,104 +8,103 @@ crontab -l | grep -v 'start_legacy_wd.sh shellcrash' | crontab -
#防止usb未加载
i=0
while [ ! -f "$CRASHDIR/configs/ShellCrash.cfg" ]; do
- [ $i -gt 20 ] && exit 1
- i=$((i + 1))
- sleep 3
+ [ $i -gt 20 ] && exit 1
+ i=$((i + 1))
+ sleep 3
done
. "$CRASHDIR"/configs/ShellCrash.cfg
-autoSSH(){
- #自动开启SSH
- [ "`uci -c /usr/share/xiaoqiang get xiaoqiang_version.version.CHANNEL`" != 'stable' ] && {
- uci -c /usr/share/xiaoqiang set xiaoqiang_version.version.CHANNEL='stable'
- uci -c /usr/share/xiaoqiang commit xiaoqiang_version.version
- }
- [ -z "$(pidof dropbear)" -o -z "$(netstat -ntul | grep :22)" ] && {
- sed -i 's/channel=.*/channel="debug"/g' /etc/init.d/dropbear
- /etc/init.d/dropbear restart
- [ -n "$mi_autoSSH_pwd" ] && echo -e "$mi_autoSSH_pwd\n$mi_autoSSH_pwd" | passwd root
- }
- #配置nvram
- [ "$(nvram get ssh_en)" = 0 ] && nvram set ssh_en=1
- [ "$(nvram get telnet_en)" = 0 ] && nvram set telnet_en=1
- nvram commit &> /dev/null
- #备份还原SSH秘钥
- [ -f "$CRASHDIR"/configs/dropbear_rsa_host_key ] && ln -sf "$CRASHDIR"/configs/dropbear_rsa_host_key /etc/dropbear/dropbear_rsa_host_key
- [ -f "$CRASHDIR"/configs/authorized_keys ] && ln -sf "$CRASHDIR"/configs/authorized_keys /etc/dropbear/authorized_keys
+autoSSH() {
+ #自动开启SSH
+ [ "$(uci -c /usr/share/xiaoqiang get xiaoqiang_version.version.CHANNEL)" != 'stable' ] && {
+ uci -c /usr/share/xiaoqiang set xiaoqiang_version.version.CHANNEL='stable'
+ uci -c /usr/share/xiaoqiang commit xiaoqiang_version.version
+ }
+ [ -z "$(pidof dropbear)" -o -z "$(netstat -ntul | grep :22)" ] && {
+ sed -i 's/channel=.*/channel="debug"/g' /etc/init.d/dropbear
+ /etc/init.d/dropbear restart
+ [ -n "$mi_autoSSH_pwd" ] && echo -e "$mi_autoSSH_pwd\n$mi_autoSSH_pwd" | passwd root
+ }
+ #配置nvram
+ [ "$(nvram get ssh_en)" = 0 ] && nvram set ssh_en=1
+ [ "$(nvram get telnet_en)" = 0 ] && nvram set telnet_en=1
+ nvram commit >/dev/null 2>&1
+ #备份还原SSH秘钥
+ [ -f "$CRASHDIR"/configs/dropbear_rsa_host_key ] && ln -sf "$CRASHDIR"/configs/dropbear_rsa_host_key /etc/dropbear/dropbear_rsa_host_key
+ [ -f "$CRASHDIR"/configs/authorized_keys ] && ln -sf "$CRASHDIR"/configs/authorized_keys /etc/dropbear/authorized_keys
}
-tunfix(){
- ko_dir=$(modinfo ip_tables | grep -Eo '/lib/modules.*/ip_tables.ko' | sed 's|/ip_tables.ko||' )
- #在/tmp创建并挂载overlay
- mkdir -p /tmp/overlay
- mkdir -p /tmp/overlay/upper
- mkdir -p /tmp/overlay/work
- mount -o noatime,lowerdir="$ko_dir",upperdir=/tmp/overlay/upper,workdir=/tmp/overlay/work -t overlay "overlay_mods_only" "$ko_dir"
- #将tun.ko链接到lib
- ln -sf "$CRASHDIR"/tools/tun.ko "$ko_dir"/tun.ko
+tunfix() {
+ ko_dir=$(modinfo ip_tables | grep -Eo '/lib/modules.*/ip_tables.ko' | sed 's|/ip_tables.ko||')
+ #在/tmp创建并挂载overlay
+ mkdir -p /tmp/overlay
+ mkdir -p /tmp/overlay/upper
+ mkdir -p /tmp/overlay/work
+ mount -o noatime,lowerdir="$ko_dir",upperdir=/tmp/overlay/upper,workdir=/tmp/overlay/work -t overlay "overlay_mods_only" "$ko_dir"
+ #将tun.ko链接到lib
+ ln -sf "$CRASHDIR"/tools/tun.ko "$ko_dir"/tun.ko
}
-tproxyfix(){
- sed -i 's/sysctl -w net.bridge.bridge-nf-call-ip/#sysctl -w net.bridge.bridge-nf-call-ip/g' /etc/init.d/qca-nss-ecm
- sysctl -w net.bridge.bridge-nf-call-iptables=0
- sysctl -w net.bridge.bridge-nf-call-ip6tables=0
+tproxyfix() {
+ sed -i 's/sysctl -w net.bridge.bridge-nf-call-ip/#sysctl -w net.bridge.bridge-nf-call-ip/g' /etc/init.d/qca-nss-ecm
+ sysctl -w net.bridge.bridge-nf-call-iptables=0
+ sysctl -w net.bridge.bridge-nf-call-ip6tables=0
}
-auto_clean(){
- #自动清理升级备份文件夹
- rm -rf /data/etc_bak
- #自动清理被写入闪存的系统日志并禁止服务
- /etc/init.d/stat_points stop 2>/dev/null
- /etc/init.d/stat_points disable 2>/dev/null
- sed -i '\#/logrotate#{ /^[[:space:]]*#/!s/^/#ShellCrash自动注释 / }' /etc/crontabs/root
- sed -i '\#/sec_cfg_bak#{ /^[[:space:]]*#/!s/^/#ShellCrash自动注释 / }' /etc/crontabs/root
- rm -rf /data/usr/log /data/usr/sec_cfg
-
+auto_clean() {
+ #自动清理升级备份文件夹
+ rm -rf /data/etc_bak
+ #自动清理被写入闪存的系统日志并禁止服务
+ /etc/init.d/stat_points stop 2>/dev/null
+ /etc/init.d/stat_points disable 2>/dev/null
+ sed -i '\#/logrotate#{ /^[[:space:]]*#/!s/^/#ShellCrash自动注释 / }' /etc/crontabs/root
+ sed -i '\#/sec_cfg_bak#{ /^[[:space:]]*#/!s/^/#ShellCrash自动注释 / }' /etc/crontabs/root
+ rm -rf /data/usr/log /data/usr/sec_cfg
+
}
-auto_start(){
- #设置init.d服务
- [ ! -x /etc/init.d/shellcrash ] && {
- cp -f "$CRASHDIR"/starts/shellcrash.procd /etc/init.d/shellcrash
- chmod 755 /etc/init.d/shellcrash
- }
- #初始化环境变量
- grep -q '^export CRASHDIR=' '/etc/profile' || {
- . "$CRASHDIR"/libs/set_profile.sh
- set_profile '/etc/profile'
- }
- #启动服务
- if [ ! -f "$CRASHDIR"/.dis_startup ] && [ ! -f "$CRASHDIR"/.start_error ]; then
- #AX6S/AX6000修复tun功能
- [ -s "$CRASHDIR"/tools/tun.ko ] && tunfix
- #小米7000/小米万兆修复tproxy
- [ -f /etc/init.d/qca-nss-ecm ] && echo "$redir_mod" | grep -q 'Tproxy' && tproxyfix
- #自动覆盖根证书文件
- [ -s "$CRASHDIR"/tools/ca-certificates.crt ] && cp -f "$CRASHDIR"/tools/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
- #启动服务
- "$CRASHDIR"/start.sh stop
- /etc/init.d/shellcrash start && /etc/init.d/shellcrash enable
- fi
+auto_start() {
+ #设置init.d服务
+ [ ! -x /etc/init.d/shellcrash ] && {
+ cp -f "$CRASHDIR"/starts/shellcrash.procd /etc/init.d/shellcrash
+ chmod 755 /etc/init.d/shellcrash
+ }
+ #初始化环境变量
+ grep -q '^export CRASHDIR=' '/etc/profile' || {
+ . "$CRASHDIR"/libs/set_profile.sh
+ set_profile '/etc/profile'
+ }
+ #启动服务
+ if [ ! -f "$CRASHDIR"/.dis_startup ] && [ ! -f "$CRASHDIR"/.start_error ]; then
+ #AX6S/AX6000修复tun功能
+ [ -s "$CRASHDIR"/tools/tun.ko ] && tunfix
+ #小米7000/小米万兆修复tproxy
+ [ -f /etc/init.d/qca-nss-ecm ] && echo "$redir_mod" | grep -q 'Tproxy' && tproxyfix
+ #自动覆盖根证书文件
+ [ -s "$CRASHDIR"/tools/ca-certificates.crt ] && cp -f "$CRASHDIR"/tools/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
+ #启动服务
+ "$CRASHDIR"/start.sh stop
+ /etc/init.d/shellcrash start && /etc/init.d/shellcrash enable
+ fi
}
-init(){
- #等待启动完成
- while ! ip a| grep -q lan; do
- sleep 10
- done
- autoSSH #软固化功能
- auto_clean #自动清理
- auto_start
- #启动自定义服务
- [ -s /data/auto_start.sh ] && /bin/sh /data/auto_start.sh &
- #兼容auto_ssh脚本
- [ -s /data/auto_ssh/auto_ssh.sh ] && /bin/sh /data/auto_ssh/auto_ssh.sh &
+init() {
+ #等待启动完成
+ while ! ip a | grep -q lan; do
+ sleep 10
+ done
+ autoSSH #软固化功能
+ auto_clean #自动清理
+ auto_start
+ #启动自定义服务
+ [ -s /data/auto_start.sh ] && /bin/sh /data/auto_start.sh &
+ #兼容auto_ssh脚本
+ [ -s /data/auto_ssh/auto_ssh.sh ] && /bin/sh /data/auto_ssh/auto_ssh.sh &
}
case "$1" in
- tunfix) tunfix ;;
- tproxyfix) tproxyfix ;;
- auto_clean) auto_clean ;;
- init) init ;;
- *)
- if [ -z "$(pidof CrashCore)" ];then
- init &
- fi
- ;;
+ tunfix) tunfix ;;
+ tproxyfix) tproxyfix ;;
+ auto_clean) auto_clean ;;
+ init) init ;;
+ *)
+ if [ -z "$(pidof CrashCore)" ]; then
+ init &
+ fi
+ ;;
esac
-
diff --git a/scripts/starts/start_error.sh b/scripts/starts/start_error.sh
index 13726b50..ecd875db 100644
--- a/scripts/starts/start_error.sh
+++ b/scripts/starts/start_error.sh
@@ -1,11 +1,11 @@
if [ "$start_old" != "ON" ] && ckcmd journalctl; then
- journalctl -u shellcrash >"$TMPDIR"/core_test.log
+ journalctl -u shellcrash >"$TMPDIR"/core_test.log
else
- PID=$(pidof CrashCore) && [ -n "$PID" ] && kill -9 "$PID" >/dev/null 2>&1
- ${COMMAND} >"$TMPDIR"/core_test.log 2>&1 &
- sleep 2
- kill $! >/dev/null 2>&1
+ PID=$(pidof CrashCore) && [ -n "$PID" ] && kill -9 "$PID" >/dev/null 2>&1
+ ${COMMAND} >"$TMPDIR"/core_test.log 2>&1 &
+ sleep 2
+ kill $! >/dev/null 2>&1
fi
touch "$CRASHDIR"/.start_error #标记启动失败,防止自启
error=$(cat "$TMPDIR"/core_test.log | grep -iEo 'error.*=.*|.*ERROR.*|.*FATAL.*')
diff --git a/scripts/starts/start_legacy.sh b/scripts/starts/start_legacy.sh
index bcbd4dc1..84e7d196 100644
--- a/scripts/starts/start_legacy.sh
+++ b/scripts/starts/start_legacy.sh
@@ -2,14 +2,14 @@
. "$CRASHDIR"/libs/check_cmd.sh
start_legacy(){
- ckcmd nohup && _nohup=nohup
- if ckcmd su && grep -q 'shellcrash:x:0:7890' /etc/passwd;then
- su shellcrash -c "$_nohup $1 >/dev/null 2>&1 & echo \$! > /tmp/ShellCrash/$2.pid"
- elif ckcmd setsid; then
+ ckcmd nohup && _nohup=nohup
+ if ckcmd su && grep -q 'shellcrash:x:0:7890' /etc/passwd;then
+ su shellcrash -c "$_nohup $1 >/dev/null 2>&1 & echo \$! > /tmp/ShellCrash/$2.pid"
+ elif ckcmd setsid; then
$_nohup setsid $1 >/dev/null 2>&1 &
echo $! > "/tmp/ShellCrash/$2.pid"
- else
- $_nohup $1 >/dev/null 2>&1 &
- echo $! > "/tmp/ShellCrash/$2.pid"
- fi
+ else
+ $_nohup $1 >/dev/null 2>&1 &
+ echo $! > "/tmp/ShellCrash/$2.pid"
+ fi
}
diff --git a/scripts/starts/start_legacy_wd.sh b/scripts/starts/start_legacy_wd.sh
index f1695ef1..bd8ef80b 100644
--- a/scripts/starts/start_legacy_wd.sh
+++ b/scripts/starts/start_legacy_wd.sh
@@ -7,24 +7,24 @@ LOCKDIR="/tmp/ShellCrash/start_$1.lock"
mkdir "$LOCKDIR" 2>/dev/null || exit 1
if [ -f "$PIDFILE" ]; then
- PID="$(cat "$PIDFILE")"
- if [ -n "$PID" ] && [ "$PID" -eq "$PID" ] 2>/dev/null; then
- if kill -0 "$PID" 2>/dev/null || [ -d "/proc/$PID" ]; then
- rm -fr "$LOCKDIR" 2>/dev/null
- exit 0
- fi
- else
- rm -f "$PIDFILE"
- fi
+ PID="$(cat "$PIDFILE")"
+ if [ -n "$PID" ] && [ "$PID" -eq "$PID" ] 2>/dev/null; then
+ if kill -0 "$PID" 2>/dev/null || [ -d "/proc/$PID" ]; then
+ rm -fr "$LOCKDIR" 2>/dev/null
+ exit 0
+ fi
+ else
+ rm -f "$PIDFILE"
+ fi
fi
#如果没有进程则拉起
if [ "$1" = "shellcrash" ]; then
- "$CRASHDIR"/start.sh start
+ "$CRASHDIR"/start.sh start
else
- [ -f "$CRASHDIR/starts/start_legacy.sh" ] && . "$CRASHDIR/starts/start_legacy.sh"
- killall bot_tg.sh 2>/dev/null
- start_legacy "$CRASHDIR/menus/bot_tg.sh" "$1"
+ [ -f "$CRASHDIR/starts/start_legacy.sh" ] && . "$CRASHDIR/starts/start_legacy.sh"
+ killall bot_tg.sh 2>/dev/null
+ start_legacy "$CRASHDIR/menus/bot_tg.sh" "$1"
fi
rm -fr "$LOCKDIR" 2>/dev/null
diff --git a/version b/version
index 936244c5..daba7b6e 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-1.9.4release
+1.9.5beta1