diff --git a/.github/workflows/core_auto_update.yml b/.github/workflows/core_auto_update.yml
index 2297dfd3..d125f6bb 100644
--- a/.github/workflows/core_auto_update.yml
+++ b/.github/workflows/core_auto_update.yml
@@ -6,43 +6,30 @@ on:
workflow_dispatch:
jobs:
- check_version:
- runs-on: ubuntu-latest
- steps:
- - name: checkout
- uses: actions/checkout@v4
- with:
- repository: reF1nd/sing-box
- ref: reF1nd-dev
- fetch-depth: 0
- - name: Check version
- run: |
- git remote add sekai https://github.com/SagerNet/sing-box.git
- git fetch --tags sekai
- version_new=$(CGO_ENABLED=0 go run ./cmd/internal/read_tag)
- version_old=$(curl -sSl https://github.com/juewuy/ShellCrash/releases/download/singbox_core_reF1nd/version)
- if [ "$version_old" != "$version_new" ];then
- echo a=$version_old >> $GITHUB_ENV
- echo b=$version_new >> $GITHUB_ENV
- else
- echo "未检查到版本更新,已退出!"
- exit 1
- fi
- auto_update_singboxp_with_wg:
- needs: check_version
- if: ${{ success() }}
+ auto_update_singboxr_dev:
permissions: write-all
uses: juewuy/ShellCrash/.github/workflows/update_singbox_core.yaml@dev
with:
tag1: reF1nd/sing-box
tag2: reF1nd-dev
- tag3: singbox_core_reF1nd
- tag5: with_quic,with_dhcp,with_wireguard,with_tailscale,with_shadowsocksr,with_utls,with_clash_api,with_gvisor
+ tag4: singboxr
+ tag5: with_gvisor,with_quic,with_dhcp,with_wireguard,with_utls,with_shadowsocksr,with_acme,with_clash_api,with_tailscale
+ tag6: gz
secrets: inherit
-
+
+ auto_update_meta_alpha:
+ permissions: write-all
+ uses: juewuy/ShellCrash/.github/workflows/update_meta_core.yaml@dev
+ with:
+ tag1: MetaCubeX/mihomo
+ tag2: Alpha
+ tag4: meta
+ tag5: with_gvisor
+ tag6: gz
+ secrets: inherit
+
cleanup:
- needs: check_version
runs-on: ubuntu-latest
steps:
- name: cleanup
diff --git a/.github/workflows/update_meta_core.yaml b/.github/workflows/update_meta_core.yaml
index 9f6c58a7..cdca176c 100644
--- a/.github/workflows/update_meta_core.yaml
+++ b/.github/workflows/update_meta_core.yaml
@@ -23,6 +23,31 @@ on:
description: 'build tags'
required: false
type: string
+ tag6:
+ description: 'ziptype(tar.gz|upx|gz)'
+ required: true
+ type: string
+
+ workflow_call:
+ inputs:
+ tag1:
+ required: true
+ type: string
+ tag2:
+ required: true
+ type: string
+ tag3:
+ required: false
+ type: string
+ tag4:
+ required: false
+ type: string
+ tag5:
+ required: false
+ type: string
+ tag6:
+ required: true
+ type: string
jobs:
go:
@@ -50,6 +75,7 @@ jobs:
id: meta
run: |
version=${{ github.event.inputs.tag2 }}
+ [ "$version" = Alpha ] && version="Alpha-$(date +"%Y%m%d")"
echo version=$version >> $GITHUB_OUTPUT
if [ -z "$TAGS" ];then
echo tags='' >> $GITHUB_OUTPUT
@@ -119,22 +145,6 @@ jobs:
uses: actions/setup-go@v6
with:
go-version: ${{needs.go.outputs.version}}
-
- - name: Set variables
- run: |
- VERSION="${GITHUB_REF_NAME,,}-$(git rev-parse --short HEAD)"
- VERSION="${VERSION//\//-}"
- PackageVersion="$(curl -s "https://api.github.com/repos/MetaCubeX/mihomo/releases/latest" | jq -r '.tag_name' | sed 's/v//g' | awk -F '.' '{$NF = $NF + 1; print}' OFS='.').${VERSION/-/.}"
- if [ -n "${{ github.event.inputs.version }}" ]; then
- VERSION=${{ github.event.inputs.version }}
- PackageVersion="${VERSION#v}"
- fi
- echo "VERSION=${VERSION}" >> $GITHUB_ENV
- echo "PackageVersion=${PackageVersion}" >> $GITHUB_ENV
- echo "BUILDTIME=$(date)" >> $GITHUB_ENV
- echo "CGO_ENABLED=0" >> $GITHUB_ENV
- echo "BUILDTAG=-extldflags --static" >> $GITHUB_ENV
- echo "GOTOOLCHAIN=local" >> $GITHUB_ENV
- name: Update CA
run: |
@@ -145,13 +155,14 @@ jobs:
- name: build core
id: build
run: |
- go env
- go build -v -tags "${TAGS}" -o meta -trimpath -ldflags "${BUILDTAG} -X 'github.com/metacubex/mihomo/constant.Version=${VERSION}' -X 'github.com/metacubex/mihomo/constant.BuildTime=${BUILDTIME}' -w -s -buildid="
+ go build -v -tags "${TAGS}" -o meta -trimpath -ldflags "-extldflags --static -X 'github.com/metacubex/mihomo/constant.Version=${VERSION}' -X 'github.com/metacubex/mihomo/constant.BuildTime=$(date)' -w -s -buildid="
+
- name: Upload file to workspace
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.name }}
path: meta
+ overwrite: true
push_to_git:
needs:
@@ -159,8 +170,9 @@ jobs:
- meta
runs-on: ubuntu-latest
env:
- RELEASE: ${{ github.event.inputs.tag3 }}
- PUSHDIR: ${{ github.event.inputs.tag4 }}
+ RELEASE: ${{ inputs.tag3 }}
+ PUSHDIR: ${{ inputs.tag4 }}
+ ZIPTYPE: ${{ inputs.tag6 }}
VERSION: ${{needs.meta.outputs.version}}
steps:
- name: Checkout ShellCrash
@@ -174,7 +186,30 @@ jobs:
with:
path: ./tmp
+ - 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 arch in amd64 armv5 armv7 arm64 386 mips-softfloat mipsle-hardfloat mipsle-softfloat;do
+ [ ! -f ./tmp/linux-${arch}/meta ] && continue
+ mv -f ./tmp/linux-${arch}/meta ./tmp/clash-linux-${arch}.upx
+ chmod +x ./tmp/clash-linux-${arch}.upx
+ case "${arch}" in
+ armv5|mips* )
+ ./upx-3.94-amd64_linux/upx --no-lzma ./tmp/clash-linux-${arch}.upx
+ ;;
+ *)
+ ./upx-3.96-amd64_linux/upx --no-lzma ./tmp/clash-linux-${arch}.upx
+ ;;
+ esac
+ done
+ rm -rf upx-3.9*
+
- name: Zip core by tar
+ if: env.ZIPTYPE == 'tar.gz'
run: |
for arch in amd64 armv5 armv7 arm64 386 mips-softfloat mipsle-hardfloat mipsle-softfloat;do
[ ! -f ./tmp/linux-${arch}/meta ] && continue
@@ -183,15 +218,24 @@ jobs:
tar --no-same-owner -zcvf ./tmp/clash-linux-${arch}.tar.gz -C ./tmp CrashCore
done
+ - name: Zip core by gz
+ if: env.ZIPTYPE == 'gz'
+ run: |
+ for arch in amd64 armv5 armv7 arm64 386 mips-softfloat mipsle-hardfloat mipsle-softfloat;do
+ [ ! -f ./tmp/linux-${arch}/meta ] && continue
+ mv -f ./tmp/linux-${arch}/meta ./tmp/clash-linux-${arch}
+ chmod +x ./tmp/clash-linux-${arch}
+ gzip ./tmp/clash-linux-${arch}
+ done
+
- name: Commit and push
if: ${{ env.PUSHDIR != '' }}
run: |
- crashcore='meta'
+ [ "${{ inputs.tag1 }}" = MetaCubeX/mihomo ] && crashcore='meta'
mkdir -p ./bin/${crashcore}
- rm -fr ./bin/${crashcore}/*
- mv -f ./tmp/clash-linux-*.tar.gz ./bin/${crashcore}/
+ mv -f ./tmp/clash-linux-* ./bin/${crashcore}/
rm -fr ./tmp
- sed -i "s/${crashcore}_v=.*/${crashcore}_v=${VERSION}/" ./bin/version
+ [ "${{ inputs.tag6 }}" = tar.gz ] && sed -i "s/${crashcore}_v=.*/${crashcore}_v=${VERSION}/" ./bin/version
git config --global user.email "github-actions[bot]@users.noreply.github.com" && git config --global user.name "github-actions[bot]"
git add . && git commit -m "更新${crashcore}内核至${VERSION}" || exit 0
git push
@@ -219,3 +263,6 @@ jobs:
with:
retain_days: 1
keep_minimum_runs: 2
+
+
+
diff --git a/.github/workflows/update_singbox_core.yaml b/.github/workflows/update_singbox_core.yaml
index c080b5de..06e90836 100644
--- a/.github/workflows/update_singbox_core.yaml
+++ b/.github/workflows/update_singbox_core.yaml
@@ -23,6 +23,11 @@ on:
description: 'build tags'
required: false
type: string
+ tag6:
+ description: 'ziptype(tar.gz|upx|gz)'
+ required: true
+ type: string
+
workflow_call:
inputs:
tag1:
@@ -40,6 +45,9 @@ on:
tag5:
required: false
type: string
+ tag6:
+ required: true
+ type: string
jobs:
go:
@@ -80,6 +88,7 @@ jobs:
git fetch --tags sekai
version=$(CGO_ENABLED=0 go run ./cmd/internal/read_tag)
[ -z "$version" ] && version=${{ inputs.tag2 }}
+ version=$(echo $version | sed 's/-reF1nd//')
echo version=$version >> $GITHUB_OUTPUT
if [ -z "$TAGS" ];then
if [ "$REPO" = 'SagerNet/sing-box' ];then
@@ -117,11 +126,11 @@ jobs:
goos: linux
goarch: mips
gomips: softfloat
- - name: linux-mipsel-softfloat
+ - name: linux-mipsle-softfloat
goos: linux
goarch: mipsle
gomips: softfloat
- - name: linux-mipsel-hardfloat
+ - name: linux-mipsle-hardfloat
goos: linux
goarch: mipsle
gomips: hardfloat
@@ -171,6 +180,7 @@ jobs:
with:
name: ${{ matrix.name }}
path: sing-box
+ overwrite: true
push_to_git:
needs:
@@ -180,6 +190,7 @@ jobs:
env:
RELEASE: ${{ inputs.tag3 }}
PUSHDIR: ${{ inputs.tag4 }}
+ ZIPTYPE: ${{ inputs.tag6 }}
VERSION: ${{needs.sing-box.outputs.version}}
steps:
- name: Checkout ShellCrash
@@ -194,18 +205,48 @@ jobs:
with:
path: ./tmp
+ - 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 arch in amd64 armv5 armv7 arm64 386 mips-softfloat mipsle-hardfloat mipsle-softfloat;do
+ [ ! -f ./tmp/linux-${arch}/sing-box ] && continue
+ mv -f ./tmp/linux-${arch}/sing-box ./tmp/singbox-linux-${arch}.upx
+ chmod +x ./tmp/singbox-linux-${arch}.upx
+ case "${arch}" in
+ armv5|mips* )
+ ./upx-3.94-amd64_linux/upx --no-lzma ./tmp/singbox-linux-${arch}.upx
+ ;;
+ *)
+ ./upx-3.96-amd64_linux/upx --no-lzma ./tmp/singbox-linux-${arch}.upx
+ ;;
+ esac
+ done
+ rm -rf upx-3.9*
+
- name: Zip core by tar
- run: |
- for arch in amd64 armv5 armv7 arm64 386 mips-softfloat mipsel-hardfloat mipsel-softfloat;do
+ if: env.ZIPTYPE == 'tar.gz'
+ run: |
+ for arch in amd64 armv5 armv7 arm64 386 mips-softfloat mipsle-hardfloat mipsle-softfloat;do
[ ! -f ./tmp/linux-${arch}/sing-box ] && continue
mv -f ./tmp/linux-${arch}/sing-box ./tmp/CrashCore
chmod +x ./tmp/CrashCore
tar --no-same-owner -zcvf ./tmp/singbox-linux-${arch}.tar.gz -C ./tmp CrashCore
done
- mv -f ./tmp/singbox-linux-mipsel-hardfloat.tar.gz ./tmp/singbox-linux-mipsle-hardfloat.tar.gz
- mv -f ./tmp/singbox-linux-mipsel-softfloat.tar.gz ./tmp/singbox-linux-mipsle-softfloat.tar.gz
- echo ${VERSION} > ./tmp/version
-
+
+ - name: Zip core by gz
+ if: env.ZIPTYPE == 'gz'
+ run: |
+ for arch in amd64 armv5 armv7 arm64 386 mips-softfloat mipsle-hardfloat mipsle-softfloat;do
+ [ ! -f ./tmp/linux-${arch}/sing-box ] && continue
+ mv -f ./tmp/linux-${arch}/sing-box ./tmp/singbox-linux-${arch}
+ chmod +x ./tmp/singbox-linux-${arch}
+ gzip ./tmp/singbox-linux-${arch}
+ done
+
- name: Commit and push
if: ${{ env.PUSHDIR != '' }}
run: |
@@ -213,10 +254,9 @@ jobs:
[ "${{ inputs.tag1 }}" = PuerNya/sing-box ] && crashcore='singboxp'
[ "${{ inputs.tag1 }}" = reF1nd/sing-box ] && crashcore='singboxr'
mkdir -p ./bin/${crashcore}
- rm -fr ./bin/${crashcore}/*
- mv -f ./tmp/singbox-linux-*.tar.gz ./bin/${crashcore}/
+ mv -f ./tmp/singbox-linux-* ./bin/${crashcore}/
rm -fr ./tmp
- sed -i "s/${crashcore}_v=.*/${crashcore}_v=${VERSION}/" ./bin/version
+ [ "${{ inputs.tag6 }}" = tar.gz ] && sed -i "s/${crashcore}_v=.*/${crashcore}_v=${VERSION}/" ./bin/version
git config --global user.email "github-actions[bot]@users.noreply.github.com" && git config --global user.name "github-actions[bot]"
git add . && git commit -m "更新${crashcore}内核至${VERSION}" || exit 0
git push
diff --git a/README_CN.md b/README_CN.md
index 489887af..ee23aee0 100644
--- a/README_CN.md
+++ b/README_CN.md
@@ -55,48 +55,48 @@
```shell
sudo -i #切换到root用户,如果需要密码,请输入密码
-export url='https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master' && wget -q --no-check-certificate -O /tmp/install.sh $url/install.sh && bash /tmp/install.sh && source /etc/profile &> /dev/null
+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)" && source /etc/profile &> /dev/null
+export url='https://gh.jwsc.eu.org/master' && bash -c "$(curl -kfsSl $url/install.sh)" && . /etc/profile &> /dev/null
```
~**路由设备使用curl安装**:
```shell
#GitHub源(可能需要代理)
-export url='https://raw.githubusercontent.com/juewuy/ShellCrash/master' && sh -c "$(curl -kfsSl $url/install.sh)" && source /etc/profile &> /dev/null
+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)" && source /etc/profile &> /dev/null
+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)" && source /etc/profile &> /dev/null
+export url='https://gh.jwsc.eu.org/master' && sh -c "$(curl -kfsSl $url/install.sh)" && . /etc/profile &> /dev/null
```
~**路由设备使用wget安装**:
```Shell
#GitHub源(可能需要代理)
-export url='https://raw.githubusercontent.com/juewuy/ShellCrash/master' && wget -q --no-check-certificate -O /tmp/install.sh $url/install.sh && sh /tmp/install.sh && source /etc/profile &> /dev/null
+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 && source /etc/profile &> /dev/null
+export url='https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master' && wget -q --no-check-certificate -O /tmp/install.sh $url/install.sh && sh /tmp/install.sh && . /etc/profile &> /dev/null
```
~**老旧设备使用低版本wge安装**:
```Shell
#作者私人http内测源
-export url='http://t.jwsc.eu.org' && wget -q -O /tmp/install.sh $url/install.sh && sh /tmp/install.sh && source /etc/profile &> /dev/null
+export url='http://t.jwsc.eu.org' && wget -q -O /tmp/install.sh $url/install.sh && sh /tmp/install.sh && . /etc/profile &> /dev/null
```
##### ~**虚拟机安装:**
@@ -107,7 +107,7 @@ export url='http://t.jwsc.eu.org' && wget -q -O /tmp/install.sh $url/install.sh
#安装必要依赖
apk add --no-cache wget openrc ca-certificates tzdata nftables iproute2 dcron
#执行安装命令
-export url='https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master' && wget -q --no-check-certificate -O /tmp/install.sh $url/install.sh && sh /tmp/install.sh && source /etc/profile &> /dev/null
+export url='https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master' && wget -q --no-check-certificate -O /tmp/install.sh $url/install.sh && sh /tmp/install.sh && . /etc/profile &> /dev/null
```
##### ~Docker安装:
diff --git a/ShellCrash.tar.gz b/ShellCrash.tar.gz
index cc6f42b0..255c2516 100644
Binary files a/ShellCrash.tar.gz and b/ShellCrash.tar.gz differ
diff --git a/bin/clashfm.tar.gz b/bin/clashfm.tar.gz
index cc6f42b0..255c2516 100644
Binary files a/bin/clashfm.tar.gz and b/bin/clashfm.tar.gz differ
diff --git a/bin/version b/bin/version
index 0130981c..9cc791f5 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.3release
+versionsh=1.9.4beta1
GeoIP_v=20251205
diff --git a/docker/README.md b/docker/README.md
index e094611c..f0a25b2d 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -15,7 +15,7 @@ docker run -d \
--name shellcrash \
-p 7890:7890 \
-p 9999:9999 \
- shellcrash:latest
+ juewuy/shellcrash:latest
```
------
@@ -59,7 +59,7 @@ docker run -d \
--cap-add SYS_ADMIN \
--device /dev/net/tun:/dev/net/tun \
--restart unless-stopped \
- shellcrash:latest
+ juewuy/shellcrash:latest
```
### 3. 配置需要路由的设备
diff --git a/docker/compose.yml b/docker/compose.yml
index a5ab9bff..9d41cd27 100644
--- a/docker/compose.yml
+++ b/docker/compose.yml
@@ -2,8 +2,8 @@ version: "3.9"
services:
shellclash:
- image: shellclash:latest
- container_name: shellclash
+ image: juewuy/shellcrash:latest
+ container_name: shellcrash
networks:
macvlan_lan:
ipv4_address: 192.168.31.222
diff --git a/install.sh b/install.sh
index 5da82c47..d8dc188c 100644
--- a/install.sh
+++ b/install.sh
@@ -1,4 +1,4 @@
-#! /bin/bash
+#!/usr/bin/env bash
# Copyright (C) Juewuy
[ -z "$url" ] && url="https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@dev"
@@ -9,10 +9,13 @@ echo "** 欢迎使用 **"
echo "** ShellCrash **"
echo "** by Juewuy **"
echo "***********************************************"
-#内置工具
+
+# Check available capacity
dir_avail() {
- df $2 $1 | awk '{ for(i=1;i<=NF;i++){ if(NR==1){ arr[i]=$i; }else{ arr[i]=arr[i]" "$i; } } } END{ for(i=1;i<=NF;i++){ print arr[i]; } }' | grep -E 'Ava|可用' | awk '{print $2}'
+ 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
@@ -45,6 +48,7 @@ error_down() {
$echo "请参考 \033[32mhttps://github.com/juewuy/ShellCrash/blob/master/README_CN.md"
$echo "\033[33m使用其他安装源重新安装!\033[0m"
}
+
#安装及初始化
set_alias() {
echo "-----------------------------------------------"
@@ -60,6 +64,7 @@ set_alias() {
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')
@@ -69,6 +74,7 @@ set_alias() {
set_alias
}
}
+
gettar() {
webget /tmp/ShellCrash.tar.gz "$url/ShellCrash.tar.gz"
if [ "$result" != "200" ]; then
diff --git a/public/fake_ip_filter.list b/public/fake_ip_filter.list
index a95ad15b..bb163c83 100644
--- a/public/fake_ip_filter.list
+++ b/public/fake_ip_filter.list
@@ -72,6 +72,7 @@ localhost.ptlogin2.qq.com
localhost.sec.qq.com
#微信登录
localhost.*.weixin.qq.com
++.kk-rays.com
#Game
#Steam
+.steamcontent.com
@@ -154,4 +155,6 @@ ps.res.netease.com
+.orayimg.com
#LOL语音
+.gcloudcs.com
-+.gcloudsdk.com
\ No newline at end of file
++.gcloudsdk.com
+#ddns
++.dynv6.net
diff --git a/public/task.list b/public/task.list
index f8bbe00c..40f5ad2b 100644
--- a/public/task.list
+++ b/public/task.list
@@ -3,9 +3,9 @@
101#$CRASHDIR/start.sh start#启动ShellCrash服务
102#$CRASHDIR/start.sh stop#停止ShellCrash服务
103#$CRASHDIR/start.sh restart#重启ShellCrash服务
-104#$CRASHDIR/start.sh update_config#更新在线订阅并重启服务
-105#$CRASHDIR/start.sh hotupdate#热更新在线订阅(不重启)
-106#$CRASHDIR/start.sh web_save#自动保存面板配置
+104#$CRASHDIR/task/task.sh update_config#更新在线订阅并重启服务
+105#$CRASHDIR/task/task.sh hotupdate#热更新在线订阅(不重启)
+106#$CRASHDIR/task/task.sh web_save_auto#自动保存面板配置
107#$CRASHDIR/task/task.sh ntp#自动同步ntp时间
111#$CRASHDIR/task/task.sh update_core#自动更新内核
diff --git a/rules/clash_providers/ShellCrash_RS_Full_BanAds.yaml b/rules/clash_providers/ShellCrash_RS_Full_BanAds.yaml
index 5295d4a2..e959126c 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全分组规则+去广告
+#ShellCrash-ruleset 全分组规则+去广告 For mihomo By Maozai 260107
#此版本为Maozai根据ACL4SSR规则修改优化而来,尽量在保持原有的基础上进行优化。
#数据源采用了DustinWin/ruleset_geodata和MetaCubeX/meta-rules-dat两个开源项目的规则,感谢原作者的辛勤付出。
@@ -8,49 +8,52 @@
#代理组
proxy-groups:
- - { name: 🚀 节点选择, type: select, proxies: [♻️ 自动选择, ✨ 自动选择(去高倍率), 🛠️ 手动切换, ⚖️ 负载均衡, 🚑 故障转移, 🎯 全球直连, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- - { name: 🛠️ 手动切换, type: select, include-all: true, exclude-type: direct }
- - { name: ♻️ 自动选择, type: url-test, interval: 600, tolerance: 50, include-all: true, exclude-type: direct }
- - { name: ✨ 自动选择(去高倍率), type: url-test, interval: 600, tolerance: 50, include-all: true, exclude-type: direct, filter: "(?i)^(?!.*(专线|专用|高级|高速|高倍率|IEPL|IPLC|x([2-9]|\\d{2,}))).*" }
- - { name: ⚖️ 负载均衡, type: load-balance, interval: 600, include-all: true, exclude-type: direct, hidden: true }
- - { name: 🚑 故障转移, type: fallback, interval: 600, include-all: true, exclude-type: direct, hidden: true }
+ - {name: 🚀 节点选择, type: select, proxies: [♻️ 自动选择, ✨ 自动选择(去高倍率), 🛠️ 手动切换, ⚖️ 负载均衡, 🚑 故障转移, 🎯 本地直连, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🛠️ 手动切换, type: select, include-all: true, proxies: [🎯 本地直连, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: ♻️ 自动选择, type: url-test, interval: 1800, tolerance: 50, include-all: true, exclude-filter: "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www)"}
+ - {name: ✨ 自动选择(去高倍率), type: url-test, interval: 1800, tolerance: 50, include-all: true, exclude-filter: "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www|专线|专用|高级|直连|急速|高速|高倍率|游戏|铂金|钻石|企业|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: 🤖 AI 平台, type: select, proxies: [🚀 节点选择, 🤖 AI节点(过滤港澳), 🎯 全球直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- - { name: 🤖 AI节点(过滤港澳), type: url-test, interval: 1800, tolerance: 50, include-all: true, filter: "(?i)^(?!.*(🇭🇰|港|🇲🇴|澳门|hk|hongkong|hong kong)).*", hidden: true }
- - { name: 📢 谷歌FCM, type: select, proxies: [🚀 节点选择, 🎯 全球直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- - { name: 🎥 奈飞视频, type: select, proxies: [🚀 节点选择, 🎥 奈飞节点, 🎯 全球直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- - { name: 🎥 奈飞节点, type: url-test, interval: 1800, tolerance: 50, include-all: true, filter: "(?i)(NF|奈飞|解锁|Netflix|NETFLIX|Media)", hidden: true }
- - { name: 📹 油管视频, type: select, proxies: [🚀 节点选择, 🎯 全球直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- - { name: 📲 电报消息, type: select, proxies: [🚀 节点选择, 🎯 全球直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- - { name: 🌍 国外媒体, type: select, proxies: [🚀 节点选择, 🎯 全球直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- - { name: 🧱 代理域名, type: select, proxies: [🚀 节点选择, 🎯 全球直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- - { name: 🎮 国外游戏, type: select, proxies: [🚀 节点选择, 🎯 全球直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
+ - {name: 🤖 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: 🎬 奈飞视频, type: select, proxies: [🚀 节点选择, 🎬 奈飞节点, 🎯 本地直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🎬 奈飞节点, type: url-test, interval: 1800, tolerance: 50, include-all: true, filter: "(?i)(NF|奈飞|解锁|Netflix|NETFLIX|Media)", hidden: true}
+ - {name: ▶️ 油管视频, type: select, proxies: [🚀 节点选择, 🎯 本地直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: 📢 谷歌推送, type: select, proxies: [🚀 节点选择, 🎯 本地直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: 📲 电报消息, type: select, proxies: [🚀 节点选择, 🎯 本地直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🌍 国际媒体, type: select, proxies: [🚀 节点选择, 🎯 本地直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🌐 国际流量, type: select, proxies: [🚀 节点选择, 🎯 本地直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🎮 外服游戏, type: select, proxies: [🚀 节点选择, 🎯 本地直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - { name: 🕹 国内游戏, type: select, proxies: [🎯 全球直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, {providers_tags}] }
- - { name: 🪟 微软服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- - { name: 🍎 苹果服务, type: select, proxies: [🎯 全球直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- - { name: 💾 trackerslist, type: select, proxies: [🎯 全球直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- - { name: 📈 网络测试, type: select, proxies: [🎯 全球直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- - { name: ↔️ 国外直连, type: select, proxies: [🎯 全球直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
- - { name: 🀄️ 国内直连, type: select, proxies: [🎯 全球直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, {providers_tags}] }
+ - {name: 🕹 国服游戏, type: select, proxies: [🎯 本地直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, {providers_tags}]}
+ - {name: 🦾 Steam平台, type: select, proxies: [🎯 本地直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🪟 微软服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🍎 苹果服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🇬 谷歌服务, type: select, proxies: [🎯 本地直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: 🧲 BT下载, type: select, proxies: [🎯 本地直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: 📈 网络测速, type: select, proxies: [🎯 本地直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
+ - {name: ↔️ 直连软件, type: select, proxies: [🎯 本地直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, {providers_tags}]}
+ - {name: 🀄️ 国内流量, type: select, proxies: [🎯 本地直连, 🚀 节点选择, ♻️ 自动选择, 🛠️ 手动切换, {providers_tags}]}
- - { name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🎯 全球直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇸🇬 狮城节点, 🇯🇵 日本节点, 🇰🇷 韩国节点, 🇺🇸 美国节点, 🇪🇺 欧洲节点, 👑 高级节点, 📉 省流节点, {providers_tags}] }
+ - {name: 🐟 漏网之鱼, type: select, proxies: [🚀 节点选择, 🎯 本地直连, ♻️ 自动选择, 🛠️ 手动切换, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
- - { name: 🛑 广告拦截, type: select, proxies: [🔴 全球拦截, 🎯 全球直连] }
- - { name: 🔒 私有网络, type: select, proxies: [DIRECT], hidden: true }
- - { name: 🔴 全球拦截, type: select, proxies: [REJECT], hidden: true }
- - { name: 🎯 全球直连, type: select, proxies: [DIRECT], hidden: true }
+ - {name: 🛑 广告拦截, type: select, proxies: [🔴 拦截, 🟢 放行]}
+ - {name: 🔒 私有网络, type: select, proxies: [DIRECT], hidden: true}
+ - {name: 🔴 拦截, type: select, proxies: [REJECT], hidden: true}
+ - {name: 🟢 放行, type: select, proxies: [PASS], hidden: true}
+ - {name: 🎯 本地直连, type: select, proxies: [DIRECT], hidden: true}
- - { name: 🇭🇰 香港节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇭🇰|港|hk|hongkong|hong kong)" }
- - { name: 🇹🇼 台湾节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇹🇼|台|tw|taiwan|tai wan)" }
- - { name: 🇸🇬 狮城节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇸🇬|新|坡|狮城|sg|singapore)" }
- - { name: 🇯🇵 日本节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇯🇵|日|东京|大阪|泉日|埼玉|jp|japan)" }
- - { name: 🇰🇷 韩国节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(KR|首尔|韩|韓|kor)" }
- - { name: 🇺🇸 美国节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇺🇸|美|us|unitedstates|united states)" }
- - { name: 🇪🇺 欧洲节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇪🇺|欧|欧洲|eu|eur|德|英|瑞|法|荷|土耳|意大利|西班牙)" }
+ - {name: 🇭🇰 香港节点, type: url-test, 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)(🇰🇷|韩|韓|首尔|kr|kor)"}
+ - {name: 🇸🇬 狮城节点, type: url-test, tolerance: 50, include-all: true, filter: "(?i)(🇸🇬|新加坡|狮城|sg|singapore)"}
- - { name: 👑 高级节点, type: url-test, interval: 1800, tolerance: 50, include-all: true, filter: "(?i)(专线|专用|高级|直连|急速|高速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)" }
- - { name: 📉 省流节点, type: url-test, interval: 1800, tolerance: 50, include-all: true, filter: "(0\\.[1-6]|低倍率|省流|大流量)" }
+ - {name: 👑 高级节点, type: url-test, interval: 1800, tolerance: 50, include-all: true, filter: "(?i)(专线|专用|高级|直连|急速|高速|高倍率|游戏|铂金|钻石|企业|VIP|Ultra|Game|IEPL|IPLC|AIA|BGP|GIA|CN2|CMI|HGC|HKT|CTM|CC|AC|x([2-9]|\\d{2,}))"}
+ - {name: 📉 省流节点, type: url-test, interval: 1800, tolerance: 50, include-all: true, filter: "(?i)(0\\.[1-6]|低倍率|省流|大流量|公益|免费|闲时|Low)"}
#规则提供者(更新mrs格式)
rule-providers:
@@ -59,185 +62,193 @@ rule-providers:
format: mrs
interval: 86400
behavior: domain
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/ai.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/ai.mrs"
youtube:
type: http
format: mrs
interval: 86400
behavior: domain
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/youtube.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/youtube.mrs"
netflix:
type: http
format: mrs
interval: 86400
behavior: domain
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/netflix.mrs"
- telegram:
- type: http
- format: mrs
- interval: 86400
- behavior: domain
- url: "https://fastly.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@refs/heads/meta/geo/geosite/telegram.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/netflix.mrs"
telegramip:
type: http
format: mrs
interval: 86400
behavior: ipcidr
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/telegramip.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/telegramip.mrs"
trackerslist:
type: http
format: mrs
interval: 86400
behavior: domain
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/trackerslist.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/trackerslist.mrs"
+ applications:
+ type: http
+ format: text
+ interval: 86400
+ behavior: classical
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/applications.list"
private:
type: http
format: mrs
interval: 86400
behavior: domain
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/private.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/private.mrs"
privateip:
type: http
format: mrs
interval: 86400
behavior: ipcidr
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/privateip.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/privateip.mrs"
networktest:
type: http
format: mrs
interval: 86400
behavior: domain
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/networktest.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/networktest.mrs"
apple-cn:
type: http
format: mrs
interval: 86400
behavior: domain
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/apple-cn.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/apple-cn.mrs"
google-cn:
type: http
format: mrs
interval: 86400
behavior: domain
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/google-cn.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/google-cn.mrs"
googlefcm:
type: http
format: mrs
interval: 86400
behavior: domain
- url: "https://fastly.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@refs/heads/meta/geo/geosite/googlefcm.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@refs/heads/meta/geo/geosite/googlefcm.mrs"
steamcn:
type: http
format: mrs
interval: 86400
behavior: domain
- url: "https://fastly.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@refs/heads/meta/geo/geosite/steam@cn.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@refs/heads/meta/geo/geosite/steam@cn.mrs"
microsoft-cn:
type: http
format: mrs
interval: 86400
behavior: domain
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/microsoft-cn.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/microsoft-cn.mrs"
games-cn:
type: http
format: mrs
interval: 86400
behavior: domain
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/games-cn.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/games-cn.mrs"
games:
type: http
format: mrs
interval: 86400
behavior: domain
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/games.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/games.mrs"
gamesip:
type: http
format: mrs
interval: 86400
behavior: ipcidr
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/gamesip.mrs"
- tld-proxy:
- type: http
- format: mrs
- interval: 86400
- behavior: domain
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/tld-proxy.mrs"
- cn-lite:
- type: http
- format: mrs
- interval: 86400
- behavior: domain
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cn-lite.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/gamesip.mrs"
mediaip:
type: http
format: mrs
interval: 86400
behavior: ipcidr
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/mediaip.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/mediaip.mrs"
media:
type: http
format: mrs
interval: 86400
behavior: domain
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/media.mrs"
- gfw:
- type: http
- format: mrs
- interval: 86400
- behavior: domain
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/gfw.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/media.mrs"
cnip:
type: http
format: mrs
interval: 86400
behavior: ipcidr
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cnip.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cnip.mrs"
proxy:
type: http
format: mrs
interval: 86400
behavior: domain
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/proxy.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/proxy.mrs"
cn:
type: http
format: mrs
interval: 86400
behavior: domain
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cn.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/cn.mrs"
ads:
type: http
format: mrs
interval: 86400
behavior: domain
- url: "https://fastly.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/ads.mrs"
+ proxy: DIRECT
+ url: "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/mihomo-ruleset/ads.mrs"
#规则顺序
rules:
+ - DOMAIN-SUFFIX,captive.apple.com,DIRECT
+ - DOMAIN-SUFFIX,kamo.teracloud.jp,DIRECT
+
- RULE-SET,privateip,🔒 私有网络,no-resolve
- RULE-SET,private,🔒 私有网络
- - RULE-SET,ads,🛑 广告拦截
- - RULE-SET,networktest,📈 网络测试
- - RULE-SET,trackerslist,💾 trackerslist
- - RULE-SET,googlefcm,📢 谷歌FCM
- - RULE-SET,google-cn,↔️ 国外直连
- - RULE-SET,steamcn,↔️ 国外直连
- - RULE-SET,microsoft-cn,🪟 微软服务
- - RULE-SET,apple-cn,🍎 苹果服务
- RULE-SET,telegramip,📲 电报消息,no-resolve
- - RULE-SET,telegram,📲 电报消息
- - RULE-SET,netflix,🎥 奈飞视频
- - RULE-SET,youtube,📹 油管视频
- - RULE-SET,ai,🤖 AI 平台
+ - RULE-SET,ads,🛑 广告拦截
+
+ - RULE-SET,networktest,📈 网络测速
+ - RULE-SET,applications,↔️ 直连软件
+ - RULE-SET,trackerslist,🧲 BT下载
+ - RULE-SET,apple-cn,🍎 苹果服务
+ - RULE-SET,microsoft-cn,🪟 微软服务
+ - RULE-SET,google-cn,🇬 谷歌服务
+ - RULE-SET,steamcn,🦾 Steam平台
+ - RULE-SET,games-cn,🕹 国服游戏
+
+ - RULE-SET,googlefcm,📢 谷歌推送
+ - RULE-SET,netflix,🎬 奈飞视频
+ - RULE-SET,youtube,▶️ 油管视频
+ - RULE-SET,ai,🤖 AI 平台
+ - RULE-SET,media,🌍 国际媒体
+ - RULE-SET,games,🎮 外服游戏
+
+ - RULE-SET,proxy,🌐 国际流量
+ - RULE-SET,cn,🀄️ 国内流量
+ - RULE-SET,gamesip,🎮 外服游戏
+ - RULE-SET,mediaip,🌍 国际媒体
+ - RULE-SET,cnip,🀄️ 国内流量
- - RULE-SET,games-cn,🕹 国内游戏
- - RULE-SET,gamesip,🎮 国外游戏
- - RULE-SET,games,🎮 国外游戏
- - RULE-SET,mediaip,🌍 国外媒体
- - RULE-SET,media,🌍 国外媒体
- - RULE-SET,tld-proxy,🧱 代理域名
- - RULE-SET,cn-lite,🀄️ 国内直连
- - RULE-SET,gfw,🧱 代理域名
- - RULE-SET,cnip,🀄️ 国内直连
- - RULE-SET,proxy,🧱 代理域名
- - RULE-SET,cn,🀄️ 国内直连
- MATCH,🐟 漏网之鱼
diff --git a/rules/clash_providers/clash_providers.list b/rules/clash_providers/clash_providers.list
index 02aaf87b..7346c0b9 100644
--- a/rules/clash_providers/clash_providers.list
+++ b/rules/clash_providers/clash_providers.list
@@ -1,4 +1,5 @@
ShellCrash-ruleset极简规则 ShellCrash_RS_Nano.yaml
+ShellCrash-ruleset全分组规则+去广告 ShellCrash_RS_Full_BanAds.yaml
DustinWin-ruleset轻量规则 DustinWin_RS_Light.yaml
DustinWin-ruleset标准规则 DustinWin_RS_Lite_NoAds.yaml
DustinWin-ruleset标准规则+去广告 DustinWin_RS_Lite.yaml
diff --git a/rules/singbox_providers/DustinWin_RS_Full.json b/rules/singbox_providers/DustinWin_RS_Full.json
index 0eab1222..d2254cbd 100644
--- a/rules/singbox_providers/DustinWin_RS_Full.json
+++ b/rules/singbox_providers/DustinWin_RS_Full.json
@@ -1,23 +1,25 @@
//DustinWin-ruleset全分组规则+去广告
{
"outbounds": [
- { "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 全球直连", {providers_tags} ] },
- { "tag": "📈 网络测试", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
+ { "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 本地直连", {providers_tags} ] },
+ { "tag": "📈 网络测试", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🤖 AI 平台", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点" ] },
- { "tag": "📋 Trackerslist", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🎮 游戏服务", "type": "selector", "outbounds": [ "🎯 全球直连", "👑 高级节点", "🚀 节点选择" ] },
- { "tag": "🪟 微软服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🇬 谷歌服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🍎 苹果服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
+ { "tag": "📋 Trackerslist", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🎮 游戏服务", "type": "selector", "outbounds": [ "🎯 本地直连", "👑 高级节点", "🚀 节点选择" ] },
+ { "tag": "🪟 微软服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🇬 谷歌服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🍎 苹果服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🌍 国外媒体", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
- { "tag": "🎮 游戏平台", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 全球直连", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
- { "tag": "🛡️ 直连域名", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🀄️ 直连 IP", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🧱 代理域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 全球直连" ] },
+ { "tag": "🎮 游戏平台", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
+ { "tag": "🛡️ 直连域名", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🀄️ 直连 IP", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🧱 代理域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
{ "tag": "📲 电报消息", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
- { "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 全球直连" ] },
- { "tag": "🎯 全球直连", "type": "selector", "outbounds": [ "DIRECT" ] },
- { "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "DIRECT" ] },
+ { "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 本地直连" ] },
+ { "tag": "🛑 广告域名", "type": "selector", "outbounds": [ "🔴 全球拦截", "🎯 本地直连" ] },
+ { "tag": "🔴 全球拦截", "type": "block" },
+ { "tag": "🎯 本地直连", "type": "direct" },
+ { "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
{ "tag": "👑 高级节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(专线|专用|高级|直连|急速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)" },
{ "tag": "📉 省流节点", "type": "urltest", "tolerance": 100, "use_all_providers": true, "include": "0\\.[1-5]|低倍率|省流|大流量" },
{ "tag": "♻️ 自动选择", "type": "urltest", "tolerance": 100, "use_all_providers": true },
@@ -30,8 +32,8 @@
],
"route": {
"rules": [
- { "rule_set": [ "private" ], "outbound": "🎯 全球直连" },
- { "rule_set": [ "ads" ], "action": "reject" },
+ { "rule_set": [ "private" ], "outbound": "🎯 本地直连" },
+ { "rule_set": [ "ads" ], "outbound": "🛑 广告域名" },
{ "rule_set": [ "trackerslist" ], "outbound": "📋 Trackerslist" },
{ "rule_set": [ "microsoft-cn" ], "outbound": "🪟 微软服务" },
{ "rule_set": [ "apple-cn" ], "outbound": "🍎 苹果服务" },
@@ -43,10 +45,10 @@
{ "rule_set": [ "networktest" ], "outbound": "📈 网络测试" },
{ "rule_set": [ "proxy" ], "outbound": "🧱 代理域名" },
{ "rule_set": [ "cn" ], "outbound": "🛡️ 直连域名" },
- { "rule_set": [ "privateip" ], "outbound": "🎯 全球直连" },
+ { "rule_set": [ "privateip" ], "outbound": "🎯 本地直连" },
{ "rule_set": [ "telegramip" ], "outbound": "📲 电报消息" },
- { "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4"},
+ { "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4", "match_only": true},
{ "rule_set": [ "cnip" ], "outbound": "🀄️ 直连 IP" },
{ "rule_set": [ "mediaip" ], "outbound": "🌍 国外媒体" },
{ "rule_set": [ "gamesip" ], "outbound": "🎮 游戏平台" }
@@ -57,126 +59,144 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/private.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "ads",
"type": "remote",
"format": "binary",
"path": "./ruleset/ads.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ads.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ads.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "trackerslist",
"type": "remote",
"format": "binary",
"path": "./ruleset/trackerslist.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/trackerslist.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/trackerslist.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "microsoft-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/microsoft-cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/microsoft-cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/microsoft-cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "apple-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/apple-cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/apple-cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/apple-cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "google-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/google-cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/google-cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/google-cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "games-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/games-cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games-cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games-cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "media",
"type": "remote",
"format": "binary",
"path": "./ruleset/media.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/media.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/media.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "games",
"type": "remote",
"format": "binary",
"path": "./ruleset/games.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "ai",
"type": "remote",
"format": "binary",
"path": "./ruleset/ai.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ai.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ai.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "networktest",
"type": "remote",
"format": "binary",
"path": "./ruleset/networktest.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/networktest.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/networktest.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "proxy",
"type": "remote",
"format": "binary",
"path": "./ruleset/proxy.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "privateip",
"type": "remote",
"format": "binary",
"path": "./ruleset/privateip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "cnip",
"type": "remote",
"format": "binary",
"path": "./ruleset/cnip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "mediaip",
"type": "remote",
"format": "binary",
"path": "./ruleset/mediaip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/mediaip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/mediaip.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "gamesip",
"type": "remote",
"format": "binary",
"path": "./ruleset/gamesip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/gamesip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/gamesip.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "telegramip",
"type": "remote",
"format": "binary",
"path": "./ruleset/telegramip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs",
+ "download_detour": "DIRECT"
}
],
"final": "🐟 漏网之鱼"
diff --git a/rules/singbox_providers/DustinWin_RS_Full_NoAds.json b/rules/singbox_providers/DustinWin_RS_Full_NoAds.json
index 9a624d99..4cae3ed6 100644
--- a/rules/singbox_providers/DustinWin_RS_Full_NoAds.json
+++ b/rules/singbox_providers/DustinWin_RS_Full_NoAds.json
@@ -1,23 +1,23 @@
//DustinWin-ruleset全分组规则
{
"outbounds": [
- { "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 全球直连", {providers_tags} ] },
- { "tag": "📈 网络测试", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
+ { "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 本地直连", {providers_tags} ] },
+ { "tag": "📈 网络测试", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🤖 AI 平台", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点" ] },
- { "tag": "📋 Trackerslist", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🎮 游戏服务", "type": "selector", "outbounds": [ "🎯 全球直连", "👑 高级节点", "🚀 节点选择" ] },
- { "tag": "🪟 微软服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🇬 谷歌服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🍎 苹果服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
+ { "tag": "📋 Trackerslist", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🎮 游戏服务", "type": "selector", "outbounds": [ "🎯 本地直连", "👑 高级节点", "🚀 节点选择" ] },
+ { "tag": "🪟 微软服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🇬 谷歌服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🍎 苹果服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
{ "tag": "🌍 国外媒体", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
- { "tag": "🎮 游戏平台", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 全球直连", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
- { "tag": "🛡️ 直连域名", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🀄️ 直连 IP", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🧱 代理域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 全球直连" ] },
+ { "tag": "🎮 游戏平台", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
+ { "tag": "🛡️ 直连域名", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🀄️ 直连 IP", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🧱 代理域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
{ "tag": "📲 电报消息", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
- { "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 全球直连" ] },
- { "tag": "🎯 全球直连", "type": "selector", "outbounds": [ "DIRECT" ] },
- { "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "DIRECT" ] },
+ { "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 本地直连" ] },
+ { "tag": "🎯 本地直连", "type": "direct" },
+ { "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
{ "tag": "👑 高级节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(专线|专用|高级|直连|急速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)" },
{ "tag": "📉 省流节点", "type": "urltest", "tolerance": 100, "use_all_providers": true, "include": "0\\.[1-5]|低倍率|省流|大流量" },
{ "tag": "♻️ 自动选择", "type": "urltest", "tolerance": 100, "use_all_providers": true },
@@ -30,7 +30,7 @@
],
"route": {
"rules": [
- { "rule_set": [ "private" ], "outbound": "🎯 全球直连" },
+ { "rule_set": [ "private" ], "outbound": "🎯 本地直连" },
{ "rule_set": [ "trackerslist" ], "outbound": "📋 Trackerslist" },
{ "rule_set": [ "microsoft-cn" ], "outbound": "🪟 微软服务" },
{ "rule_set": [ "apple-cn" ], "outbound": "🍎 苹果服务" },
@@ -42,10 +42,10 @@
{ "rule_set": [ "networktest" ], "outbound": "📈 网络测试" },
{ "rule_set": [ "proxy" ], "outbound": "🧱 代理域名" },
{ "rule_set": [ "cn" ], "outbound": "🛡️ 直连域名" },
- { "rule_set": [ "privateip" ], "outbound": "🎯 全球直连" },
+ { "rule_set": [ "privateip" ], "outbound": "🎯 本地直连" },
{ "rule_set": [ "telegramip" ], "outbound": "📲 电报消息" },
- { "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4"},
+ { "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4", "match_only": true},
{ "rule_set": [ "cnip" ], "outbound": "🀄️ 直连 IP" },
{ "rule_set": [ "mediaip" ], "outbound": "🌍 国外媒体" },
{ "rule_set": [ "gamesip" ], "outbound": "🎮 游戏平台" }
@@ -56,119 +56,136 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/private.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "trackerslist",
"type": "remote",
"format": "binary",
"path": "./ruleset/trackerslist.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/trackerslist.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/trackerslist.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "microsoft-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/microsoft-cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/microsoft-cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/microsoft-cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "apple-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/apple-cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/apple-cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/apple-cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "google-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/google-cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/google-cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/google-cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "games-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/games-cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games-cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games-cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "media",
"type": "remote",
"format": "binary",
"path": "./ruleset/media.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/media.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/media.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "games",
"type": "remote",
"format": "binary",
"path": "./ruleset/games.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "ai",
"type": "remote",
"format": "binary",
"path": "./ruleset/ai.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ai.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ai.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "networktest",
"type": "remote",
"format": "binary",
"path": "./ruleset/networktest.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/networktest.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/networktest.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "proxy",
"type": "remote",
"format": "binary",
"path": "./ruleset/proxy.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "privateip",
"type": "remote",
"format": "binary",
"path": "./ruleset/privateip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "cnip",
"type": "remote",
"format": "binary",
"path": "./ruleset/cnip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "mediaip",
"type": "remote",
"format": "binary",
"path": "./ruleset/mediaip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/mediaip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/mediaip.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "gamesip",
"type": "remote",
"format": "binary",
"path": "./ruleset/gamesip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/gamesip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/gamesip.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "telegramip",
"type": "remote",
"format": "binary",
"path": "./ruleset/telegramip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs",
+ "download_detour": "DIRECT"
}
],
"final": "🐟 漏网之鱼"
diff --git a/rules/singbox_providers/DustinWin_RS_Light.json b/rules/singbox_providers/DustinWin_RS_Light.json
index 53294fd1..c94b6a50 100644
--- a/rules/singbox_providers/DustinWin_RS_Light.json
+++ b/rules/singbox_providers/DustinWin_RS_Light.json
@@ -1,12 +1,12 @@
//DustinWin-ruleset轻量规则
{
"outbounds": [
- { "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 全球直连", {providers_tags} ] },
- { "tag": "🧱 代理域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 全球直连" ] },
+ { "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 本地直连", {providers_tags} ] },
+ { "tag": "🧱 代理域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
{ "tag": "📲 电报消息", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
- { "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 全球直连" ] },
- { "tag": "🎯 全球直连", "type": "selector", "outbounds": [ "DIRECT" ] },
- { "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "DIRECT" ] },
+ { "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 本地直连" ] },
+ { "tag": "🎯 本地直连", "type": "direct" },
+ { "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
{ "tag": "👑 高级节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(专线|专用|高级|直连|急速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)" },
{ "tag": "📉 省流节点", "type": "urltest", "tolerance": 100, "use_all_providers": true, "include": "0\\.[1-5]|低倍率|省流|大流量" },
{ "tag": "♻️ 自动选择", "type": "urltest", "tolerance": 100, "use_all_providers": true },
@@ -19,15 +19,15 @@
],
"route": {
"rules": [
- { "rule_set": [ "private" ], "outbound": "🎯 全球直连" },
+ { "rule_set": [ "private" ], "outbound": "🎯 本地直连" },
{ "rule_set": [ "tld-proxy" ], "outbound": "🧱 代理域名" },
{ "rule_set": [ "proxy" ], "outbound": "🧱 代理域名" },
- { "rule_set": [ "cn" ], "outbound": "🎯 全球直连" },
- { "rule_set": [ "privateip" ], "outbound": "🎯 全球直连" },
+ { "rule_set": [ "cn" ], "outbound": "🎯 本地直连" },
+ { "rule_set": [ "privateip" ], "outbound": "🎯 本地直连" },
{ "rule_set": [ "telegramip" ], "outbound": "📲 电报消息" },
- { "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4"},
- { "rule_set": [ "cnip" ], "outbound": "🎯 全球直连" }
+ { "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4", "match_only": true},
+ { "rule_set": [ "cnip" ], "outbound": "🎯 本地直连" }
],
"rule_set": [
{
@@ -35,49 +35,56 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "private",
"type": "remote",
"format": "binary",
"path": "./ruleset/private.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "tld-proxy",
"type": "remote",
"format": "binary",
"path": "./ruleset/tld-proxy.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/tld-proxy.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/tld-proxy.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "proxy",
"type": "remote",
"format": "binary",
"path": "./ruleset/proxy.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "privateip",
"type": "remote",
"format": "binary",
"path": "./ruleset/privateip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "cnip",
"type": "remote",
"format": "binary",
"path": "./ruleset/cnip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "telegramip",
"type": "remote",
"format": "binary",
"path": "./ruleset/telegramip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs",
+ "download_detour": "DIRECT"
}
],
"final": "🐟 漏网之鱼"
diff --git a/rules/singbox_providers/DustinWin_RS_Lite.json b/rules/singbox_providers/DustinWin_RS_Lite.json
index 7e305497..44748625 100644
--- a/rules/singbox_providers/DustinWin_RS_Lite.json
+++ b/rules/singbox_providers/DustinWin_RS_Lite.json
@@ -1,21 +1,23 @@
//DustinWin-ruleset标准规则+去广告
{
"outbounds": [
- { "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 全球直连", {providers_tags} ] },
- { "tag": "📈 网络测试", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
+ { "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 本地直连", {providers_tags} ] },
+ { "tag": "📈 网络测试", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🤖 AI 平台", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点" ] },
- { "tag": "📋 Trackerslist", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🎮 游戏服务", "type": "selector", "outbounds": [ "🎯 全球直连", "👑 高级节点", "🚀 节点选择" ] },
- { "tag": "🪟 微软服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🇬 谷歌服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🍎 苹果服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🛡️ 直连域名", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🀄️ 直连 IP", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🧱 代理域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 全球直连" ] },
+ { "tag": "📋 Trackerslist", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🎮 游戏服务", "type": "selector", "outbounds": [ "🎯 本地直连", "👑 高级节点", "🚀 节点选择" ] },
+ { "tag": "🪟 微软服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🇬 谷歌服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🍎 苹果服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🛡️ 直连域名", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🀄️ 直连 IP", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🧱 代理域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
{ "tag": "📲 电报消息", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
- { "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 全球直连" ] },
- { "tag": "🎯 全球直连", "type": "selector", "outbounds": [ "DIRECT" ] },
- { "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "DIRECT" ] },
+ { "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 本地直连" ] },
+ { "tag": "🛑 广告域名", "type": "selector", "outbounds": [ "🔴 全球拦截", "🎯 本地直连" ] },
+ { "tag": "🔴 全球拦截", "type": "block" },
+ { "tag": "🎯 本地直连", "type": "direct" },
+ { "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
{ "tag": "👑 高级节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(专线|专用|高级|直连|急速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)" },
{ "tag": "📉 省流节点", "type": "urltest", "tolerance": 100, "use_all_providers": true, "include": "0\\.[1-5]|低倍率|省流|大流量" },
{ "tag": "♻️ 自动选择", "type": "urltest", "tolerance": 100, "use_all_providers": true },
@@ -28,8 +30,8 @@
],
"route": {
"rules": [
- { "rule_set": [ "private" ], "outbound": "🎯 全球直连" },
- { "rule_set": [ "ads" ], "action": "reject" },
+ { "rule_set": [ "private" ], "outbound": "🎯 本地直连" },
+ { "rule_set": [ "ads" ], "outbound": "🛑 广告域名" },
{ "rule_set": [ "trackerslist" ], "outbound": "📋 Trackerslist" },
{ "rule_set": [ "microsoft-cn" ], "outbound": "🪟 微软服务" },
{ "rule_set": [ "apple-cn" ], "outbound": "🍎 苹果服务" },
@@ -39,10 +41,10 @@
{ "rule_set": [ "networktest" ], "outbound": "📈 网络测试" },
{ "rule_set": [ "proxy" ], "outbound": "🧱 代理域名" },
{ "rule_set": [ "cn" ], "outbound": "🛡️ 直连域名" },
- { "rule_set": [ "privateip" ], "outbound": "🎯 全球直连" },
+ { "rule_set": [ "privateip" ], "outbound": "🎯 本地直连" },
{ "rule_set": [ "telegramip" ], "outbound": "📲 电报消息" },
- { "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4"},
+ { "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4", "match_only": true},
{ "rule_set": [ "cnip" ], "outbound": "🀄️ 直连 IP" }
],
"rule_set": [
@@ -51,98 +53,112 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/private.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "ads",
"type": "remote",
"format": "binary",
"path": "./ruleset/ads.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ads.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ads.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "trackerslist",
"type": "remote",
"format": "binary",
"path": "./ruleset/trackerslist.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/trackerslist.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/trackerslist.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "microsoft-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/microsoft-cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/microsoft-cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/microsoft-cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "apple-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/apple-cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/apple-cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/apple-cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "google-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/google-cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/google-cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/google-cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "games-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/games-cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games-cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games-cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "ai",
"type": "remote",
"format": "binary",
"path": "./ruleset/ai.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ai.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ai.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "networktest",
"type": "remote",
"format": "binary",
"path": "./ruleset/networktest.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/networktest.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/networktest.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "proxy",
"type": "remote",
"format": "binary",
"path": "./ruleset/proxy.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "privateip",
"type": "remote",
"format": "binary",
"path": "./ruleset/privateip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "cnip",
"type": "remote",
"format": "binary",
"path": "./ruleset/cnip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "telegramip",
"type": "remote",
"format": "binary",
"path": "./ruleset/telegramip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs",
+ "download_detour": "DIRECT"
}
],
"final": "🐟 漏网之鱼"
diff --git a/rules/singbox_providers/DustinWin_RS_Lite_NoAds.json b/rules/singbox_providers/DustinWin_RS_Lite_NoAds.json
index d8c8cb87..a5eba229 100644
--- a/rules/singbox_providers/DustinWin_RS_Lite_NoAds.json
+++ b/rules/singbox_providers/DustinWin_RS_Lite_NoAds.json
@@ -1,21 +1,21 @@
//DustinWin-ruleset标准规则
{
"outbounds": [
- { "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 全球直连", {providers_tags} ] },
- { "tag": "📈 网络测试", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
+ { "tag": "🚀 节点选择", "type": "selector", "outbounds": [ "♻️ 自动选择", "👉 手动选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", "🎯 本地直连", {providers_tags} ] },
+ { "tag": "📈 网络测试", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
{ "tag": "🤖 AI 平台", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点" ] },
- { "tag": "📋 Trackerslist", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🎮 游戏服务", "type": "selector", "outbounds": [ "🎯 全球直连", "👑 高级节点", "🚀 节点选择" ] },
- { "tag": "🪟 微软服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🇬 谷歌服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🍎 苹果服务", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🛡️ 直连域名", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🀄️ 直连 IP", "type": "selector", "outbounds": [ "🎯 全球直连", "🚀 节点选择" ] },
- { "tag": "🧱 代理域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 全球直连" ] },
+ { "tag": "📋 Trackerslist", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🎮 游戏服务", "type": "selector", "outbounds": [ "🎯 本地直连", "👑 高级节点", "🚀 节点选择" ] },
+ { "tag": "🪟 微软服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🇬 谷歌服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🍎 苹果服务", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🛡️ 直连域名", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🀄️ 直连 IP", "type": "selector", "outbounds": [ "🎯 本地直连", "🚀 节点选择" ] },
+ { "tag": "🧱 代理域名", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
{ "tag": "📲 电报消息", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags} ] },
- { "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 全球直连" ] },
- { "tag": "🎯 全球直连", "type": "selector", "outbounds": [ "DIRECT" ] },
- { "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "DIRECT" ] },
+ { "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": [ "🚀 节点选择", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇯🇵 日本节点", "🇸🇬 新加坡节点", "🇺🇸 美国节点", "👑 高级节点", "📉 省流节点", {providers_tags}, "🎯 本地直连" ] },
+ { "tag": "🎯 本地直连", "type": "direct" },
+ { "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
{ "tag": "👑 高级节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(专线|专用|高级|直连|急速|高倍率|游戏|game|IEPL|IPLC|AIA|CTM|CC|AC)" },
{ "tag": "📉 省流节点", "type": "urltest", "tolerance": 100, "use_all_providers": true, "include": "0\\.[1-5]|低倍率|省流|大流量" },
{ "tag": "♻️ 自动选择", "type": "urltest", "tolerance": 100, "use_all_providers": true },
@@ -28,7 +28,7 @@
],
"route": {
"rules": [
- { "rule_set": [ "private" ], "outbound": "🎯 全球直连" },
+ { "rule_set": [ "private" ], "outbound": "🎯 本地直连" },
{ "rule_set": [ "trackerslist" ], "outbound": "📋 Trackerslist" },
{ "rule_set": [ "microsoft-cn" ], "outbound": "🪟 微软服务" },
{ "rule_set": [ "apple-cn" ], "outbound": "🍎 苹果服务" },
@@ -38,10 +38,10 @@
{ "rule_set": [ "networktest" ], "outbound": "📈 网络测试" },
{ "rule_set": [ "proxy" ], "outbound": "🧱 代理域名" },
{ "rule_set": [ "cn" ], "outbound": "🛡️ 直连域名" },
- { "rule_set": [ "privateip" ], "outbound": "🎯 全球直连" },
+ { "rule_set": [ "privateip" ], "outbound": "🎯 本地直连" },
{ "rule_set": [ "telegramip" ], "outbound": "📲 电报消息" },
- { "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4"},
+ { "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4", "match_only": true},
{ "rule_set": [ "cnip" ], "outbound": "🀄️ 直连 IP" }
],
@@ -51,91 +51,104 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/private.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/private.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "trackerslist",
"type": "remote",
"format": "binary",
"path": "./ruleset/trackerslist.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/trackerslist.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/trackerslist.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "microsoft-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/microsoft-cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/microsoft-cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/microsoft-cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "apple-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/apple-cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/apple-cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/apple-cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "google-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/google-cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/google-cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/google-cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "games-cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/games-cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games-cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/games-cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "ai",
"type": "remote",
"format": "binary",
"path": "./ruleset/ai.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ai.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/ai.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "networktest",
"type": "remote",
"format": "binary",
"path": "./ruleset/networktest.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/networktest.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/networktest.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "proxy",
"type": "remote",
"format": "binary",
"path": "./ruleset/proxy.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/proxy.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "cn",
"type": "remote",
"format": "binary",
"path": "./ruleset/cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "privateip",
"type": "remote",
"format": "binary",
"path": "./ruleset/privateip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "cnip",
"type": "remote",
"format": "binary",
"path": "./ruleset/cnip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "telegramip",
"type": "remote",
"format": "binary",
"path": "./ruleset/telegramip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/telegramip.srs",
+ "download_detour": "DIRECT"
}
],
"final": "🐟 漏网之鱼"
diff --git a/rules/singbox_providers/ShellCrash_RS_Full_BanAds.json b/rules/singbox_providers/ShellCrash_RS_Full_BanAds.json
new file mode 100644
index 00000000..d771d946
--- /dev/null
+++ b/rules/singbox_providers/ShellCrash_RS_Full_BanAds.json
@@ -0,0 +1,273 @@
+//ShellCrash-ruleset 全分组规则+去广告 For Sing-box By Maozai 260107
+{
+ "outbounds": [
+ { "tag": "🚀 节点选择", "type": "selector", "outbounds": ["♻️ 自动选择", "✨ 自动选择(去高倍率)", "🛠️ 手动切换", "🎯 本地直连", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
+ { "tag": "🛠️ 手动切换", "type": "selector", "use_all_providers": true, "outbounds": ["🎯 本地直连", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
+ { "tag": "♻️ 自动选择", "type": "urltest", "use_all_providers": true, "exclude": "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www)" },
+ { "tag": "✨ 自动选择(去高倍率)", "type": "urltest", "use_all_providers": true, "exclude": "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www|专线|专用|高级|直连|急速|高速|高倍率|游戏|铂金|钻石|企业|VIP|Ultra|Game|IEPL|IPLC|AIA|BGP|GIA|CN2|CMI|HGC|HKT|CTM|CC|AC|x([2-9]|[0-9][0-9]+))" },
+
+ { "tag": "🤖 AI 平台", "type": "selector", "outbounds": ["🚀 节点选择", "🤖 AI节点(过滤港澳)", "🎯 本地直连", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
+ { "tag": "🤖 AI节点(过滤港澳)", "type": "urltest", "use_all_providers": true, "exclude": "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www|🇭🇰|港|🇲🇴|澳门|hk|hongkong|hong kong)" },
+ { "tag": "🎬 奈飞视频", "type": "selector", "outbounds": ["🚀 节点选择", "🎬 奈飞节点", "🎯 本地直连", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
+ { "tag": "🎬 奈飞节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(NF|奈飞|解锁|Netflix|NETFLIX|Media)" },
+ { "tag": "▶️ 油管视频", "type": "selector", "outbounds": ["🚀 节点选择", "🎯 本地直连", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
+ { "tag": "📢 谷歌推送", "type": "selector", "outbounds": ["🚀 节点选择", "🎯 本地直连", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
+ { "tag": "📲 电报消息", "type": "selector", "outbounds": ["🚀 节点选择", "🎯 本地直连", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
+ { "tag": "🌍 国际媒体", "type": "selector", "outbounds": ["🚀 节点选择", "🎯 本地直连", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
+ { "tag": "🌐 国际流量", "type": "selector", "outbounds": ["🚀 节点选择", "🎯 本地直连", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
+ { "tag": "🎮 外服游戏", "type": "selector", "outbounds": ["🚀 节点选择", "🎯 本地直连", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
+
+ { "tag": "🕹 国服游戏", "type": "selector", "outbounds": ["🎯 本地直连", "🚀 节点选择", "♻️ 自动选择", "🛠️ 手动切换", {providers_tags}] },
+ { "tag": "🦾 Steam平台", "type": "selector", "outbounds": ["🎯 本地直连", "🚀 节点选择", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
+ { "tag": "🪟 微软服务", "type": "selector", "outbounds": ["🎯 本地直连", "🚀 节点选择", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
+ { "tag": "🍎 苹果服务", "type": "selector", "outbounds": ["🎯 本地直连", "🚀 节点选择", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
+ { "tag": "🇬 谷歌服务", "type": "selector", "outbounds": ["🎯 本地直连", "🚀 节点选择", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
+ { "tag": "🧲 BT下载", "type": "selector", "outbounds": ["🎯 本地直连", "🚀 节点选择", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
+ { "tag": "📈 网络测速", "type": "selector", "outbounds": ["🎯 本地直连", "🚀 节点选择", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
+ { "tag": "↔️ 直连软件", "type": "selector", "outbounds": ["🎯 本地直连", "🚀 节点选择", "♻️ 自动选择", "🛠️ 手动切换", {providers_tags}] },
+ { "tag": "🀄️ 国内流量", "type": "selector", "outbounds": ["🎯 本地直连", "🚀 节点选择", "♻️ 自动选择", "🛠️ 手动切换", {providers_tags}] },
+
+ { "tag": "🐟 漏网之鱼", "type": "selector", "outbounds": ["🚀 节点选择", "🎯 本地直连", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
+
+
+ { "tag": "🛑 广告拦截", "type": "selector", "outbounds": ["⛔ 禁止连接","🔀 规则放行", "🎯 本地直连"] },
+ { "tag": "⛔ 禁止连接", "type": "block" },
+ { "tag": "🔀 规则放行", "type": "pass" },
+ { "tag": "🎯 本地直连", "type": "direct" },
+ { "tag": "GLOBAL", "type": "selector", "outbounds": [ "🚀 节点选择", "🎯 本地直连" ] },
+
+ { "tag": "🇭🇰 香港节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(🇭🇰|港|hk|hongkong|hong kong)" },
+ { "tag": "🇹🇼 台湾节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(🇹🇼|台|tw|taiwan|tai wan)" },
+ { "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)(🇰🇷|韩|韓|首尔|kr|kor)" },
+ { "tag": "🇸🇬 狮城节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(🇸🇬|新加坡|狮城|sg|singapore)" },
+
+ { "tag": "👑 高级节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(专线|专用|高级|直连|急速|高速|高倍率|游戏|铂金|钻石|企业|VIP|Ultra|Game|IEPL|IPLC|AIA|BGP|GIA|CN2|CMI|HGC|HKT|CTM|CC|AC|x([2-9]|[0-9][0-9]+))" },
+ { "tag": "📉 省流节点", "type": "urltest", "use_all_providers": true, "include": "(?i)(0[.][1-5]|低倍率|省流|大流量|公益|免费|闲时|Low)" }
+ ],
+ "route": {
+ "rules": [
+ { "domain_suffix": ["captive.apple.com"], "outbound": "DIRECT" },
+ { "domain_suffix": ["kamo.teracloud.jp"], "outbound": "DIRECT" },
+
+ { "rule_set": ["private"], "outbound": "🎯 本地直连" },
+ { "rule_set": ["ads"], "outbound": "🛑 广告拦截" },
+
+ { "rule_set": ["networktest"], "outbound": "📈 网络测速" },
+ { "rule_set": ["applications"], "outbound": "↔️ 直连软件" },
+ { "rule_set": ["trackerslist"], "outbound": "🧲 BT下载" },
+ { "rule_set": ["apple-cn"], "outbound": "🍎 苹果服务" },
+ { "rule_set": ["microsoft-cn"], "outbound": "🪟 微软服务" },
+ { "rule_set": ["google-cn"], "outbound": "🇬 谷歌服务" },
+ { "rule_set": ["steamcn"], "outbound": "🦾 Steam平台" },
+ { "rule_set": ["games-cn"], "outbound": "🕹 国服游戏" },
+
+ { "rule_set": ["googlefcm"], "outbound": "📢 谷歌推送" },
+ { "rule_set": ["netflix"], "outbound": "🎬 奈飞视频" },
+ { "rule_set": ["youtube"], "outbound": "▶️ 油管视频" },
+ { "rule_set": ["ai"], "outbound": "🤖 AI 平台" },
+ { "rule_set": ["media"], "outbound": "🌍 国际媒体" },
+ { "rule_set": ["games"], "outbound": "🎮 外服游戏" },
+
+ { "rule_set": ["proxy"], "outbound": "🌐 国际流量" },
+ { "rule_set": ["cn"], "outbound": "🀄️ 国内流量" },
+
+ { "rule_set": ["privateip"], "outbound": "🎯 本地直连" },
+ { "rule_set": ["telegramip"], "outbound": "📲 电报消息" },
+
+ { "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4" },
+ { "rule_set": ["gamesip"], "outbound": "🎮 外服游戏" },
+ { "rule_set": ["mediaip"], "outbound": "🌍 国际媒体" },
+ { "rule_set": ["cnip"], "outbound": "🀄️ 国内流量" }
+ ],
+ "rule_set": [
+ {
+ "tag": "private",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/private.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/private.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "ads",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/ads.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/ads.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "networktest",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/networktest.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/networktest.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "applications",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/applications.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/applications.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "trackerslist",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/trackerslist.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/trackerslist.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "apple-cn",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/apple-cn.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/apple-cn.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "microsoft-cn",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/microsoft-cn.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/microsoft-cn.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "google-cn",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/google-cn.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/google-cn.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "steamcn",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/steamcn.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@refs/heads/sing/geo/geosite/steam%40cn.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "games-cn",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/games-cn.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/games-cn.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "googlefcm",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/googlefcm.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@refs/heads/sing/geo/geosite/googlefcm.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "netflix",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/netflix.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/netflix.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "youtube",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/youtube.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/youtube.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "ai",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/ai.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/ai.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "media",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/media.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/media.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "games",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/games.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/games.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "proxy",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/proxy.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/proxy.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "cn",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/cn.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/cn.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "privateip",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/privateip.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/privateip.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "telegramip",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/telegramip.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/telegramip.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "gamesip",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/gamesip.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/gamesip.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "mediaip",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/mediaip.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/mediaip.srs",
+ "download_detour": "DIRECT"
+ },
+ {
+ "tag": "cnip",
+ "type": "remote",
+ "format": "binary",
+ "path": "./ruleset/cnip.srs",
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@refs/heads/sing-box-ruleset/cnip.srs",
+ "download_detour": "DIRECT"
+ }
+ ],
+ "final": "🐟 漏网之鱼"
+ }
+}
diff --git a/rules/singbox_providers/ShellCrash_RS_Nano.json b/rules/singbox_providers/ShellCrash_RS_Nano.json
index 72784ae4..1a08c9b9 100644
--- a/rules/singbox_providers/ShellCrash_RS_Nano.json
+++ b/rules/singbox_providers/ShellCrash_RS_Nano.json
@@ -1,16 +1,16 @@
//ShellCrash-ruleset极简规则
{
"outbounds": [
- { "tag": "🚀 节点选择", "type": "selector", "outbounds": [ {providers_tags}, "DIRECT" ], "use_all_providers": true },
- { "tag": "🎯 全球直连", "type": "selector", "outbounds": [ "DIRECT", "🚀 节点选择" ] }
+ { "tag": "🚀 节点选择", "type": "selector", "outbounds": [ {providers_tags}, "🎯 本地直连" ], "use_all_providers": true },
+ { "tag": "🎯 本地直连", "type": "direct" }
],
"route": {
"rules": [
- { "rule_set": [ "privateip" ], "outbound": "🎯 全球直连" },
- { "rule_set": [ "cn" ], "outbound": "🎯 全球直连" },
+ { "rule_set": [ "privateip" ], "outbound": "🎯 本地直连" },
+ { "rule_set": [ "cn" ], "outbound": "🎯 本地直连" },
- { "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4"},
- { "rule_set": [ "cnip" ], "outbound": "🎯 全球直连" }
+ { "action": "resolve", "server": "dns_proxy", "strategy": "prefer_ipv4", "match_only": true},
+ { "rule_set": [ "cnip" ], "outbound": "🎯 本地直连" }
],
"rule_set": [
{
@@ -18,21 +18,24 @@
"type": "remote",
"format": "binary",
"path": "./ruleset/cn.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cn.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "privateip",
"type": "remote",
"format": "binary",
"path": "./ruleset/privateip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/privateip.srs",
+ "download_detour": "DIRECT"
},
{
"tag": "cnip",
"type": "remote",
"format": "binary",
"path": "./ruleset/cnip.srs",
- "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs"
+ "url": "https://testingcf.jsdelivr.net/gh/DustinWin/ruleset_geodata@sing-box-ruleset/cnip.srs",
+ "download_detour": "DIRECT"
}
],
"final": "🚀 节点选择"
diff --git a/rules/singbox_providers/singbox_providers.list b/rules/singbox_providers/singbox_providers.list
index fea7b7c9..fb2d8d14 100644
--- a/rules/singbox_providers/singbox_providers.list
+++ b/rules/singbox_providers/singbox_providers.list
@@ -1,4 +1,5 @@
ShellCrash-ruleset极简规则 ShellCrash_RS_Nano.json
+ShellCrash-ruleset全分组规则+去广告 ShellCrash_RS_Full_BanAds.json
DustinWin-ruleset轻量规则 DustinWin_RS_Light.json
DustinWin-ruleset标准规则 DustinWin_RS_Lite_NoAds.json
DustinWin-ruleset标准规则+去广告 DustinWin_RS_Lite.json
diff --git a/scripts/init.sh b/scripts/init.sh
index 2745fab6..558a9660 100644
--- a/scripts/init.sh
+++ b/scripts/init.sh
@@ -1,161 +1,6 @@
#!/bin/sh
# Copyright (C) Juewuy
-setdir() {
- dir_avail() {
- df $2 $1 | awk '{ for(i=1;i<=NF;i++){ if(NR==1){ arr[i]=$i; }else{ arr[i]=arr[i]" "$i; } } } END{ for(i=1;i<=NF;i++){ print arr[i]; } }' | grep -E 'Ava|可用' | awk '{print $2}'
- }
- set_usb_dir() {
- echo -e "请选择安装目录"
- du -hL /mnt | awk '{print " "NR" "$2" "$1}'
- read -p "请输入相应数字 > " num
- dir=$(du -hL /mnt | awk '{print $2}' | sed -n "$num"p)
- if [ -z "$dir" ]; then
- echo -e "\033[31m输入错误!请重新设置!\033[0m"
- set_usb_dir
- fi
- }
- set_asus_dir() {
- echo -e "请选择U盘目录"
- du -hL /tmp/mnt | awk -F/ 'NF<=4' | awk '{print " "NR" "$2" "$1}'
- read -p "请输入相应数字 > " num
- dir=$(du -hL /tmp/mnt | awk -F/ 'NF<=4' | awk '{print $2}' | sed -n "$num"p)
- if [ ! -f "$dir/asusware.arm/etc/init.d/S50downloadmaster" ]; then
- echo -e "\033[31m未找到下载大师自启文件:$dir/asusware.arm/etc/init.d/S50downloadmaster,请检查设置!\033[0m"
- set_asus_dir
- fi
- }
- set_cust_dir() {
- echo "-----------------------------------------------"
- echo "可用路径 剩余空间:"
- df -h | awk '{print $6,$4}' | sed 1d
- echo "路径是必须带 / 的格式,注意写入虚拟内存(/tmp,/opt,/sys...)的文件会在重启后消失!!!"
- read -p "请输入自定义路径 > " dir
- if [ "$(dir_avail $dir)" = 0 ] || [ -n "$(echo $dir | grep -E 'tmp|opt|sys')" ]; then
- echo "\033[31m路径错误!请重新设置!\033[0m"
- set_cust_dir
- fi
- }
- echo "-----------------------------------------------"
- if [ -n "$systype" ]; then
- [ "$systype" = "Padavan" ] && dir=/etc/storage
- [ "$systype" = "mi_snapshot" ] && {
- echo -e "\033[33m检测到当前设备为小米官方系统,请选择安装位置\033[0m"
- [ -d /data ] && $echo " 1 安装到 /data 目录,剩余空间:$(dir_avail /data -h)(支持软固化功能)"
- [ -d /userdisk ] && $echo " 2 安装到 /userdisk 目录,剩余空间:$(dir_avail /userdisk -h)(支持软固化功能)"
- [ -d /data/other_vol ] && $echo " 3 安装到 /data/other_vol 目录,剩余空间:$(dir_avail /data/other_vol -h)(支持软固化功能)"
- $echo " 4 安装到自定义目录(不推荐,不明勿用!)"
- echo " 0 退出安装"
- echo "-----------------------------------------------"
- read -p "请输入相应数字 > " num
- case "$num" in
- 1)
- dir=/data
- ;;
- 2)
- dir=/userdisk
- ;;
- 3)
- dir=/data/other_vol
- ;;
- 4)
- set_cust_dir
- ;;
- *)
- exit 1
- ;;
- esac
- }
- [ "$systype" = "asusrouter" ] && {
- echo -e "\033[33m检测到当前设备为华硕固件,请选择安装方式\033[0m"
- echo -e " 1 基于USB设备安装(限23年9月之前固件,须插入\033[31m任意\033[0mUSB设备)"
- echo -e " 2 基于自启脚本安装(仅支持梅林及部分非koolshare官改固件)"
- echo -e " 3 基于U盘+下载大师安装(支持所有固件,限ARM设备,须插入U盘或移动硬盘)"
- echo -e " 0 退出安装"
- echo "-----------------------------------------------"
- read -p "请输入相应数字 > " num
- case "$num" in
- 1)
- read -p "将脚本安装到USB存储/系统闪存?(1/0) > " res
- [ "$res" = "1" ] && set_usb_dir || dir=/jffs
- usb_status=1
- ;;
- 2)
- echo -e "如无法正常开机启动,请重新使用USB方式安装!"
- sleep 2
- dir=/jffs
- ;;
- 3)
- echo -e "请先在路由器网页后台安装下载大师并启用,之后选择外置存储所在目录!"
- sleep 2
- set_asus_dir
- ;;
- *)
- exit 1
- ;;
- esac
- }
- [ "$systype" = "ng_snapshot" ] && dir=/tmp/mnt
- else
- echo -e "\033[33m安装ShellCrash至少需要预留约1MB的磁盘空间\033[0m"
- echo -e " 1 在\033[32m/etc目录\033[0m下安装(适合root用户)"
- echo -e " 2 在\033[32m/usr/share目录\033[0m下安装(适合Linux系统)"
- echo -e " 3 在\033[32m当前用户目录\033[0m下安装(适合非root用户)"
- echo -e " 4 在\033[32m外置存储\033[0m中安装"
- echo -e " 5 手动设置安装目录"
- echo -e " 0 退出安装"
- echo "-----------------------------------------------"
- read -p "请输入相应数字 > " num
- #设置目录
- case "$num" in
- 1)
- dir=/etc
- ;;
- 2)
- dir=/usr/share
- ;;
- 3)
- dir=~/.local/share
- mkdir -p ~/.config/systemd/user
- ;;
- 4)
- set_usb_dir
- ;;
- 5)
- echo "-----------------------------------------------"
- echo "可用路径 剩余空间:"
- df -h | awk '{print $6,$4}' | sed 1d
- echo "路径是必须带 / 的格式,注意写入虚拟内存(/tmp,/opt,/sys...)的文件会在重启后消失!!!"
- read -p "请输入自定义路径 > " dir
- if [ -z "$dir" ]; then
- echo -e "\033[31m路径错误!请重新设置!\033[0m"
- setdir
- fi
- ;;
- *)
- echo "安装已取消"
- exit 1
- ;;
- esac
- fi
-
- if [ ! -w $dir ]; then
- echo -e "\033[31m没有$dir目录写入权限!请重新设置!\033[0m" && sleep 1 && setdir
- else
- echo -e "目标目录\033[32m$dir\033[0m空间剩余:$(dir_avail $dir -h)"
- read -p "确认安装?(1/0) > " res
- [ "$res" = "1" ] && CRASHDIR=$dir/ShellCrash || setdir
- fi
-}
-setconfig() { #脚本配置工具
- #参数1代表变量名,参数2代表变量值,参数3即文件路径
- [ -z "$3" ] && configpath="$CRASHDIR"/configs/ShellCrash.cfg || configpath="${3}"
- if grep -q "^${1}=" "$configpath"; then
- sed -i "s#^${1}=.*#${1}=${2}#g" "$configpath"
- else
- printf '%s=%s\n' "$1" "$2" >>"$configpath"
- fi
-}
#特殊固件识别及标记
[ -f "/etc/storage/started_script.sh" ] && { #老毛子固件
systype=Padavan
@@ -176,22 +21,26 @@ grep -qE '/(docker|lxc|kubepods|crio|containerd)/' /proc/1/cgroup || [ -f /run/.
#检查环境变量
[ "$systype" = 'container' ] && CRASHDIR='/etc/ShellCrash'
[ -z "$CRASHDIR" ] && [ -n "$clashdir" ] && CRASHDIR="$clashdir"
-[ -z "$CRASHDIR" ] && [ -d /tmp/SC_tmp ] && setdir
+[ -z "$CRASHDIR" ] && [ -d /tmp/SC_tmp ] && . /tmp/SC_tmp/menus/set_crashdir.sh && set_crashdir
#移动文件
-mkdir -p ${CRASHDIR}
-mv -f /tmp/SC_tmp/* ${CRASHDIR} 2>/dev/null
-
+mkdir -p "$CRASHDIR"
+rm -rf /tmp/SC_tmp/menus/set_crashdir.sh
+mv -f /tmp/SC_tmp/* "$CRASHDIR" 2>/dev/null
+##############################
+#注意目录变更
+CFG_PATH="$CRASHDIR"/configs/ShellCrash.cfg
+. "$CRASHDIR"/libs/set_config.sh
+. "$CRASHDIR"/libs/set_profile.sh
#初始化
-mkdir -p ${CRASHDIR}/configs
-[ -f "${CRASHDIR}/configs/ShellCrash.cfg" ] || echo '#ShellCrash配置文件,不明勿动!' >${CRASHDIR}/configs/ShellCrash.cfg
+mkdir -p "$CRASHDIR"/configs
+[ -f "$CFG_PATH" ] || echo '#ShellCrash配置文件,不明勿动!' >"$CFG_PATH"
#判断系统类型写入不同的启动文件
[ -w /usr/lib/systemd/system ] && sysdir=/usr/lib/systemd/system
[ -w /etc/systemd/system ] && sysdir=/etc/systemd/system
if [ -f /etc/rc.common -a "$(cat /proc/1/comm)" = "procd" ]; then
#设为init.d方式启动
- cp -f ${CRASHDIR}/shellcrash.procd /etc/init.d/shellcrash
+ cp -f "$CRASHDIR"/starts/shellcrash.procd /etc/init.d/shellcrash
chmod 755 /etc/init.d/shellcrash
- rm -rf ${CRASHDIR}/shellcrash.openrc
elif [ -n "$sysdir" -a "$USER" = "root" -a "$(cat /proc/1/comm)" = "systemd" ]; then
#创建shellcrash用户
userdel shellcrash 2>/dev/null
@@ -204,41 +53,46 @@ elif [ -n "$sysdir" -a "$USER" = "root" -a "$(cat /proc/1/comm)" = "systemd" ];
echo "shellcrash:x:0:7890::/home/shellcrash:/bin/sh" >>/etc/passwd
fi
#配置systemd
- mv -f ${CRASHDIR}/shellcrash.service $sysdir/shellcrash.service 2>/dev/null
- sed -i "s%/etc/ShellCrash%$CRASHDIR%g" $sysdir/shellcrash.service
+ mv -f "$CRASHDIR"/starts/shellcrash.service "$sysdir"/shellcrash.service 2>/dev/null
+ sed -i "s%/etc/ShellCrash%$CRASHDIR%g" "$sysdir"/shellcrash.service
systemctl daemon-reload
+ rm -rf "$CRASHDIR"/starts/shellcrash.procd
elif rc-status -r >/dev/null 2>&1; then
#设为openrc方式启动
- cp -f ${CRASHDIR}/shellcrash.openrc /etc/init.d/shellcrash
+ mv -f "$CRASHDIR"/starts/shellcrash.openrc /etc/init.d/shellcrash
chmod 755 /etc/init.d/shellcrash
- rm -rf ${CRASHDIR}/shellcrash.procd
+ rm -rf "$CRASHDIR"/starts/shellcrash.procd
else
#设为保守模式启动
setconfig start_old 已开启
+ rm -rf "$CRASHDIR"/starts/shellcrash.procd
fi
+rm -rf "$CRASHDIR"/starts/shellcrash.service
+rm -rf "$CRASHDIR"/starts/shellcrash.openrc
#修饰文件及版本号
command -v bash >/dev/null 2>&1 && shtype=bash
[ -x /bin/ash ] && shtype=ash
-for file in start.sh task.sh menu.sh; do
- sed -i "s|/bin/sh|/bin/$shtype|" ${CRASHDIR}/${file} 2>/dev/null
- chmod 755 ${CRASHDIR}/${file} 2>/dev/null
+#批量授权
+for file in start.sh starts/bfstart.sh starts/afstart.sh starts/fw_stop.sh menu.sh menus/task_cmd.sh menus/bot_tg.sh; do
+ sed -i "s|/bin/sh|/bin/$shtype|" "$CRASHDIR/$file" 2>/dev/null
+ chmod +x "$CRASHDIR/$file" 2>/dev/null
done
setconfig versionsh_l $version
#生成用于执行启动服务的变量文件
-[ ! -f ${CRASHDIR}/configs/command.env ] && {
+[ ! -f "$CRASHDIR"/configs/command.env ] && {
TMPDIR='/tmp/ShellCrash'
- BINDIR=${CRASHDIR}
- touch ${CRASHDIR}/configs/command.env
- setconfig TMPDIR ${TMPDIR} ${CRASHDIR}/configs/command.env
- setconfig BINDIR ${BINDIR} ${CRASHDIR}/configs/command.env
+ BINDIR="$CRASHDIR"
+ touch "$CRASHDIR"/configs/command.env
+ setconfig TMPDIR "$TMPDIR" "$CRASHDIR"/configs/command.env
+ setconfig BINDIR "$BINDIR" "$CRASHDIR"/configs/command.env
}
-if [ -n "$(grep 'crashcore=singbox' ${CRASHDIR}/configs/ShellCrash.cfg)" ]; then
+if [ -n "$(grep 'crashcore=singbox' "$CFG_PATH")" ]; then
COMMAND='"$TMPDIR/CrashCore run -D $BINDIR -C $TMPDIR/jsons"'
else
COMMAND='"$TMPDIR/CrashCore -d $BINDIR -f $TMPDIR/config.yaml"'
fi
-setconfig COMMAND "$COMMAND" ${CRASHDIR}/configs/command.env
+setconfig COMMAND "$COMMAND" "$CRASHDIR"/configs/command.env
#设置防火墙执行模式
grep -q 'firewall_mod' "$CRASHDIR/configs/ShellClash.cfg" 2>/dev/null || {
firewall_mod=iptables
@@ -251,17 +105,10 @@ grep -q 'firewall_mod' "$CRASHDIR/configs/ShellClash.cfg" 2>/dev/null || {
[ -w /opt/etc/profile ] && profile=/opt/etc/profile
[ -w /jffs/configs/profile.add ] && profile=/jffs/configs/profile.add
[ -z "$profile" ] && profile=/etc/profile
-set_profile() {
- [ -z "$my_alias" ] && my_alias=crash
- sed -i "/ShellCrash\/menu.sh/"d "$1"
- echo "alias ${my_alias}=\"$shtype $CRASHDIR/menu.sh\"" >>"$1" #设置快捷命令环境变量
- sed -i '/export CRASHDIR=*/'d "$1"
- echo "export CRASHDIR=\"$CRASHDIR\"" >>"$1" #设置路径环境变量
-}
if [ -n "$profile" ]; then
set_profile "$profile"
#适配zsh环境变量
- zsh --version >/dev/null 2>&1 && [ -z "$(cat $HOME/.zshrc 2>/dev/null | grep CRASHDIR)" ] && set_profile '$HOME/.zshrc'
+ zsh --version >/dev/null 2>&1 && [ -z "$(cat $HOME/.zshrc 2>/dev/null | grep CRASHDIR)" ] && set_profile "$HOME/.zshrc"
setconfig my_alias "$my_alias"
else
echo -e "\033[33m无法写入环境变量!请检查安装权限!\033[0m"
@@ -269,30 +116,39 @@ else
fi
#梅林/Padavan额外设置
[ -n "$initdir" ] && {
- sed -i '/ShellCrash初始化/'d $initdir
- touch $initdir
- echo "$CRASHDIR/start.sh init & #ShellCrash初始化脚本" >>$initdir
- chmod a+rx $initdir 2>/dev/null
- setconfig initdir $initdir
+ touch "$initdir"
+ sed -i '/ShellCrash初始化/'d "$initdir"
+ echo "$CRASHDIR/starts/general_init.sh & #ShellCrash初始化脚本" >>"$initdir"
+ chmod 755 "$CRASHDIR"/starts/general_init.sh
+ chmod a+rx "$initdir" 2>/dev/null
+ setconfig initdir "$initdir"
}
#Padavan额外设置
[ -f "/etc/storage/started_script.sh" ] && mount -t tmpfs -o remount,rw,size=45M tmpfs /tmp #增加/tmp空间以适配新的内核压缩方式
#镜像化OpenWrt(snapshot)额外设置
if [ "$systype" = "mi_snapshot" -o "$systype" = "ng_snapshot" ]; then
- chmod 755 ${CRASHDIR}/misnap_init.sh
- uci delete firewall.ShellClash 2>/dev/null
+ chmod 755 "$CRASHDIR"/starts/snapshot_init.sh
+ if [ "$systype" = "mi_snapshot" ];then
+ path="/data/shellcrash_init.sh"
+ setconfig CRASHDIR "$CRASHDIR" "$CRASHDIR"/starts/snapshot_init.sh
+ mv -f "$CRASHDIR"/starts/snapshot_init.sh "$path"
+ [ ! -f /data/auto_start.sh ] && echo '#用于自定义需要开机启动的功能或者命令,会在开机后自动运行' > /data/auto_start.sh
+ else
+ path="$CRASHDIR"/starts/snapshot_init.sh
+ fi
+ uci delete firewall.auto_ssh 2>/dev/null
uci delete firewall.ShellCrash 2>/dev/null
uci set firewall.ShellCrash=include
uci set firewall.ShellCrash.type='script'
- uci set firewall.ShellCrash.path="$CRASHDIR/misnap_init.sh"
+ uci set firewall.ShellCrash.path="$path"
uci set firewall.ShellCrash.enabled='1'
uci commit firewall
else
- rm -rf ${CRASHDIR}/misnap_init.sh
+ rm -rf "$CRASHDIR"/starts/snapshot_init.sh
fi
#华硕USB启动额外设置
[ "$usb_status" = "1" ] && {
- echo "$CRASHDIR/start.sh init & #ShellCrash初始化脚本" >${CRASHDIR}/asus_usb_mount.sh
+ echo "$CRASHDIR/start.sh init & #ShellCrash初始化脚本" >"$CRASHDIR"/asus_usb_mount.sh
nvram set script_usbmount="$CRASHDIR/asus_usb_mount.sh"
nvram commit
}
@@ -307,7 +163,7 @@ fi
setconfig firewall_area '1'
setconfig firewall_mod 'nftables'
setconfig release_type 'master'
- setconfig start_old '未开启'
+ setconfig start_old 'OFF'
echo "$CRASHDIR/menu.sh" >> /etc/profile
cat > /usr/bin/crash <<'EOF'
#!/bin/sh
@@ -322,57 +178,56 @@ setconfig systype $systype
rm -rf /tmp/*rash*gz
rm -rf /tmp/SC_tmp
#转换&清理旧版本文件
-mkdir -p ${CRASHDIR}/yamls
-mkdir -p ${CRASHDIR}/jsons
-mkdir -p ${CRASHDIR}/tools
-mkdir -p ${CRASHDIR}/task
-mkdir -p ${CRASHDIR}/ruleset
+mkdir -p "$CRASHDIR"/yamls
+mkdir -p "$CRASHDIR"/jsons
+mkdir -p "$CRASHDIR"/tools
+mkdir -p "$CRASHDIR"/task
+mkdir -p "$CRASHDIR"/ruleset
for file in config.yaml.bak user.yaml proxies.yaml proxy-groups.yaml rules.yaml others.yaml; do
- mv -f ${CRASHDIR}/$file ${CRASHDIR}/yamls/$file 2>/dev/null
+ mv -f "$CRASHDIR"/"$file" "$CRASHDIR"/yamls/"$file" 2>/dev/null
done
-[ ! -L ${CRASHDIR}/config.yaml ] && mv -f ${CRASHDIR}/config.yaml ${CRASHDIR}/yamls/config.yaml 2>/dev/null
+[ ! -L "$CRASHDIR"/config.yaml ] && mv -f "$CRASHDIR"/config.yaml "$CRASHDIR"/yamls/config.yaml 2>/dev/null
for file in fake_ip_filter mac web_save servers.list fake_ip_filter.list fallback_filter.list singbox_providers.list clash_providers.list; do
- mv -f ${CRASHDIR}/$file ${CRASHDIR}/configs/$file 2>/dev/null
+ mv -f "$CRASHDIR"/"$file" "$CRASHDIR"/configs/"$file" 2>/dev/null
done
#配置文件改名
-mv -f ${CRASHDIR}/mark ${CRASHDIR}/configs/ShellCrash.cfg 2>/dev/null
-mv -f ${CRASHDIR}/configs/ShellClash.cfg ${CRASHDIR}/configs/ShellCrash.cfg 2>/dev/null
+mv -f "$CRASHDIR"/configs/ShellClash.cfg "$CFG_PATH" 2>/dev/null
#数据库改名
-mv -f ${CRASHDIR}/geosite.dat ${CRASHDIR}/GeoSite.dat 2>/dev/null
-mv -f ${CRASHDIR}/ruleset/geosite-cn.srs ${CRASHDIR}/ruleset/cn.srs 2>/dev/null
-mv -f ${CRASHDIR}/ruleset/geosite-cn.mrs ${CRASHDIR}/ruleset/cn.mrs 2>/dev/null
+mv -f "$CRASHDIR"/geosite.dat "$CRASHDIR"/GeoSite.dat 2>/dev/null
+mv -f "$CRASHDIR"/ruleset/geosite-cn.srs "$CRASHDIR"/ruleset/cn.srs 2>/dev/null
+mv -f "$CRASHDIR"/ruleset/geosite-cn.mrs "$CRASHDIR"/ruleset/cn.mrs 2>/dev/null
#数据库移动
-mv -f ${CRASHDIR}/*.srs ${CRASHDIR}/ruleset/ 2>/dev/null
-mv -f ${CRASHDIR}/*.mrs ${CRASHDIR}/ruleset/ 2>/dev/null
-#内核改名
-mv -f ${CRASHDIR}/clash ${CRASHDIR}/CrashCore 2>/dev/null
-#内核压缩
-[ -f ${CRASHDIR}/CrashCore ] && tar -zcf ${CRASHDIR}/CrashCore.tar.gz -C ${CRASHDIR} CrashCore
+mv -f "$CRASHDIR"/*.srs "$CRASHDIR"/ruleset/ 2>/dev/null
+mv -f "$CRASHDIR"/*.mrs "$CRASHDIR"/ruleset/ 2>/dev/null
for file in dropbear_rsa_host_key authorized_keys tun.ko ShellDDNS.sh; do
- mv -f ${CRASHDIR}/$file ${CRASHDIR}/tools/$file 2>/dev/null
+ mv -f "$CRASHDIR"/"$file" "$CRASHDIR"/tools/"$file" 2>/dev/null
done
-for file in cron task.sh task.list; do
- mv -f ${CRASHDIR}/$file ${CRASHDIR}/task/$file 2>/dev/null
+for file in cron task.list; do
+ mv -f "$CRASHDIR"/"$file" "$CRASHDIR"/task/"$file" 2>/dev/null
done
+mv -f "$CRASHDIR"/menus/task_cmd.sh "$CRASHDIR"/task/task.sh 2>/dev/null
#旧版文件清理
userdel shellclash >/dev/null 2>&1
sed -i '/shellclash/d' /etc/passwd
sed -i '/shellclash/d' /etc/group
rm -rf /etc/init.d/clash
-rm -rf ${CRASHDIR}/rules
+rm -rf "$CRASHDIR"/rules
[ "$systype" = "mi_snapshot" -a "$CRASHDIR" != '/data/clash' ] && rm -rf /data/clash
-for file in CrashCore clash.sh getdate.sh core.new clashservice log shellcrash.service mark? mark.bak; do
- rm -rf ${CRASHDIR}/$file
+for file in webget.sh misnap_init.sh core.new; do
+ rm -f "$CRASHDIR/$file"
done
#旧版变量改名
-sed -i "s/clashcore/crashcore/g" $configpath
-sed -i "s/clash_v/core_v/g" $configpath
-sed -i "s/clash.meta/meta/g" $configpath
-sed -i "s/ShellClash/ShellCrash/g" $configpath
-sed -i "s/cpucore=armv8/cpucore=arm64/g" $configpath
-sed -i "s/redir_mod=Nft基础/redir_mod=Redir模式/g" $configpath
-sed -i "s/redir_mod=Nft混合/redir_mod=Tproxy模式/g" $configpath
-sed -i "s/redir_mod=Tproxy混合/redir_mod=Tproxy模式/g" $configpath
-sed -i "s/redir_mod=纯净模式/firewall_area=4/g" $configpath
+sed -i "s/clashcore/crashcore/g" "$CFG_PATH"
+sed -i "s/clash_v/core_v/g" "$CFG_PATH"
+sed -i "s/clash.meta/meta/g" "$CFG_PATH"
+sed -i "s/ShellClash/ShellCrash/g" "$CFG_PATH"
+sed -i "s/cpucore=armv8/cpucore=arm64/g" "$CFG_PATH"
+sed -i "s/redir_mod=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=纯净模式/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"
diff --git a/scripts/libs/README.md b/scripts/libs/README.md
new file mode 100644
index 00000000..380299a7
--- /dev/null
+++ b/scripts/libs/README.md
@@ -0,0 +1,11 @@
+用于存放脚本内置工具的脚本
+
+引用方式必须为:
+
+```shell
+. "$CRASHDIR"/libs/xxx.sh
+```
+
+返回码必须是return x而不能是exit x
+
+此处脚本内容不应包含文字输出和log输出
\ No newline at end of file
diff --git a/scripts/libs/check_autostart.sh b/scripts/libs/check_autostart.sh
new file mode 100644
index 00000000..12942bd5
--- /dev/null
+++ b/scripts/libs/check_autostart.sh
@@ -0,0 +1,16 @@
+check_autostart(){
+ if [ "$start_old" = ON ];then
+ [ ! -f "$CRASHDIR"/.dis_startup ] && return 0
+ elif [ -f /etc/rc.common -a "$(cat /proc/1/comm)" = "procd" ]; then
+ [ -n "$(find /etc/rc.d -name '*shellcrash')" ] && return 0
+ elif ckcmd systemctl; then
+ [ "$(systemctl is-enabled shellcrash.service 2>&1)" = enabled ] && return 0
+ elif grep -q 's6' /proc/1/comm; then
+ [ -f /etc/s6-overlay/s6-rc.d/user/contents.d/afstart ] && return 0
+ elif rc-status -r >/dev/null 2>&1; then
+ rc-update show default | grep -q "shellcrash" && return 0
+ else
+ return 1
+ fi
+ return 1
+}
diff --git a/scripts/libs/check_cmd.sh b/scripts/libs/check_cmd.sh
new file mode 100644
index 00000000..8a1319a5
--- /dev/null
+++ b/scripts/libs/check_cmd.sh
@@ -0,0 +1,7 @@
+ckcmd() {
+ if command -v sh >/dev/null 2>&1;then
+ command -v "$1" >/dev/null 2>&1
+ else
+ type "$1" >/dev/null 2>&1
+ fi
+}
diff --git a/scripts/libs/check_cpucore.sh b/scripts/libs/check_cpucore.sh
new file mode 100644
index 00000000..cae95fee
--- /dev/null
+++ b/scripts/libs/check_cpucore.sh
@@ -0,0 +1,14 @@
+
+check_cpucore(){ #自动获取内核架构
+ cputype=$(uname -ms | tr ' ' '_' | tr '[A-Z]' '[a-z]')
+ [ -n "$(echo $cputype | grep -E "linux.*armv.*")" ] && cpucore="armv5"
+ [ -n "$(echo $cputype | grep -E "linux.*armv7.*")" ] && [ -n "$(cat /proc/cpuinfo | grep vfp)" ] && [ ! -d /jffs ] && cpucore="armv7"
+ [ -n "$(echo $cputype | grep -E "linux.*aarch64.*|linux.*armv8.*")" ] && cpucore="arm64"
+ [ -n "$(echo $cputype | grep -E "linux.*86.*")" ] && cpucore="386"
+ [ -n "$(echo $cputype | grep -E "linux.*86_64.*")" ] && cpucore="amd64"
+ if [ -n "$(echo $cputype | grep -E "linux.*mips.*")" ];then
+ mipstype=$(echo -n I | hexdump -o 2>/dev/null | awk '{ print substr($2,6,1); exit}') #通过判断大小端判断mips或mipsle
+ [ "$mipstype" = "0" ] && cpucore="mips-softfloat" || cpucore="mipsle-softfloat"
+ fi
+ [ -n "$cpucore" ] && setconfig cpucore $cpucore
+}
diff --git a/scripts/libs/check_dir_avail.sh b/scripts/libs/check_dir_avail.sh
new file mode 100644
index 00000000..b2a68f7b
--- /dev/null
+++ b/scripts/libs/check_dir_avail.sh
@@ -0,0 +1,5 @@
+#检查目录剩余空间——$1:目标路径 $2:-h参数
+dir_avail() {
+ df -h >/dev/null 2>&1 && h="$2"
+ df -P $h "${1:-.}" 2>/dev/null | awk 'NR==2 {print $4}'
+}
diff --git a/scripts/libs/check_target.sh b/scripts/libs/check_target.sh
new file mode 100644
index 00000000..b8efc811
--- /dev/null
+++ b/scripts/libs/check_target.sh
@@ -0,0 +1,8 @@
+if echo "$crashcore" | grep -q 'singbox'; then
+ target=singbox
+ format=json
+else
+ target=clash
+ format=yaml
+fi
+core_config="$CRASHDIR/${format}s/config.$format"
diff --git a/scripts/libs/compare.sh b/scripts/libs/compare.sh
new file mode 100644
index 00000000..c0f3a684
--- /dev/null
+++ b/scripts/libs/compare.sh
@@ -0,0 +1,10 @@
+compare() { #对比文件
+ if [ ! -f "$1" ] || [ ! -f "$2" ]; then
+ return 1
+ elif ckcmd cmp; then
+ cmp -s "$1" "$2"
+ return $?
+ else
+ [ "$(cat "$1")" = "$(cat "$2")" ] && return 0 || return 1
+ fi
+}
\ No newline at end of file
diff --git a/scripts/libs/core_tools.sh b/scripts/libs/core_tools.sh
new file mode 100644
index 00000000..536b2b00
--- /dev/null
+++ b/scripts/libs/core_tools.sh
@@ -0,0 +1,80 @@
+
+
+[ -n "$(find --help 2>&1 | grep -o size)" ] && find_para=' -size +2000' #find命令兼容
+
+core_unzip() { #$1:需要解压的文件 $2:目标文件名
+ if echo "$1" |grep -q 'tar.gz$' ;then
+ [ "$BINDIR" = "$TMPDIR" ] && rm -rf "$TMPDIR"/CrashCore #小闪存模式防止空间不足
+ [ -n "$(tar --help 2>&1 | grep -o 'no-same-owner')" ] && tar_para='--no-same-owner' #tar命令兼容
+ mkdir -p "$TMPDIR"/core_tmp
+ tar -zxf "$1" ${tar_para} -C "$TMPDIR"/core_tmp/
+ for file in $(find "$TMPDIR"/core_tmp $find_para 2>/dev/null); do
+ [ -f "$file" ] && [ -n "$(echo $file | sed 's#.*/##' | grep -iE '(CrashCore|sing|meta|mihomo|clash|pre)')" ] && mv -f "$file" "$TMPDIR"/"$2"
+ done
+ rm -rf "$TMPDIR"/core_tmp
+ elif echo "$1" |grep -q '.gz$' ;then
+ gunzip -c "$1" > "$TMPDIR"/"$2"
+ elif echo "$1" |grep -q '.upx$' ;then
+ ln -sf "$1" "$TMPDIR"/"$2"
+ else
+ mv -f "$1" "$TMPDIR"/"$2"
+ fi
+ chmod +x "$TMPDIR"/"$2"
+}
+core_find(){
+ if [ ! -f "$TMPDIR"/CrashCore ];then
+ core_dir=$(find "$BINDIR"/CrashCore.* $find_para 2>/dev/null)
+ [ -n "$core_dir" ] && core_unzip "$core_dir" CrashCore
+ fi
+}
+core_check(){
+ [ -n "$(pidof CrashCore)" ] && "$CRASHDIR"/start.sh stop #停止内核服务防止内存不足
+ core_unzip "$1" core_new
+ sbcheck=$(echo "$crashcore" | grep 'singbox')
+ v=''
+ if [ -n "$sbcheck" ] && "$TMPDIR"/core_new -h 2>&1 | grep -q 'sing-box'; then
+ v=$("$TMPDIR"/core_new version 2>/dev/null | grep version | awk '{print $3}')
+ COMMAND='"$TMPDIR/CrashCore run -D $BINDIR -C $TMPDIR/jsons"'
+ elif [ -z "$sbcheck" ] && "$TMPDIR"/core_new -h 2>&1 | grep -q '\-t';then
+ v=$("$TMPDIR"/core_new -v 2>/dev/null | head -n 1 | sed 's/ linux.*//;s/.* //')
+ COMMAND='"$TMPDIR/CrashCore -d $BINDIR -f $TMPDIR/config.yaml"'
+ fi
+ if [ -z "$v" ]; then
+ rm -rf "$TMPDIR"/core_new
+ rm -rf "$1"
+ return 2
+ else
+ rm -f "$BINDIR"/CrashCore.tar.gz "$BINDIR"/CrashCore.gz "$BINDIR"/CrashCore.upx
+ mv -f "$TMPDIR"/core_new "$TMPDIR"/CrashCore
+ if [ -f "$1" ];then
+ mv -f "$1" "$BINDIR/CrashCore.${zip_type}"
+ else
+ gzip -c "$TMPDIR"/CrashCore > "$BINDIR"/CrashCore.gz
+ 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/CrashCore.${zip_type}" "bin/$crashcore/${target}-linux-${cpucore}.${zip_type}"
+ else
+ zip_type=$(echo "$custcorelink" | grep -oE 'tar.gz$')
+ [ -z "$zip_type" ] && zip_type=$(echo "$custcorelink" | grep -oE 'gz$')
+ [ -n "$zip_type" ] && webget "$TMPDIR/CrashCore.${zip_type}" "$custcorelink"
+ fi
+ #校验内核
+ if [ "$?" = 0 ];then
+ core_check "$TMPDIR/CrashCore.${zip_type}"
+ else
+ rm -rf "$TMPDIR/CrashCore.${zip_type}"
+ return 1
+ fi
+}
diff --git a/scripts/libs/gen_base64.sh b/scripts/libs/gen_base64.sh
new file mode 100644
index 00000000..a3b36a87
--- /dev/null
+++ b/scripts/libs/gen_base64.sh
@@ -0,0 +1,26 @@
+#生成指定位数的加密秘钥,符合ss2022协议
+gen_random() {
+ if ckcmd openssl;then
+ openssl rand --base64 "$1"
+ elif ckcmd base64;then
+ head -c "$1" /dev/urandom | base64 | tr -d '\n'
+ elif busybox base64 --help >/dev/null 2>&1;then
+ head -c "$1" /dev/urandom | base64 | tr -d '\n'
+ elif ckcmd uuencode;then
+ head -c "$1" /dev/urandom | uuencode -m - | sed -n '2p'
+ else
+ return 1
+ fi
+}
+#对指定字符串进行base64转码
+gen_base64() {
+ if ckcmd base64;then
+ echo -n "$1" | base64 | tr -d '\n'
+ elif busybox base64 --help >/dev/null 2>&1;then
+ echo -n "$1" | busybox base64 | tr -d '\n'
+ elif ckcmd openssl;then
+ echo -n "$1" | openssl base64 -A
+ else
+ return 1
+ fi
+}
\ No newline at end of file
diff --git a/scripts/libs/get_config.sh b/scripts/libs/get_config.sh
new file mode 100644
index 00000000..333c85ac
--- /dev/null
+++ b/scripts/libs/get_config.sh
@@ -0,0 +1,22 @@
+. "$CRASHDIR"/configs/command.env >/dev/null 2>&1
+. "$CRASHDIR"/configs/ShellCrash.cfg
+
+[ -z "$mix_port" ] && mix_port=7890
+[ -z "$redir_port" ] && redir_port=7892
+[ -z "$tproxy_port" ] && tproxy_port=7893
+[ -z "$db_port" ] && db_port=9999
+[ -z "$dns_port" ] && dns_port=1053
+[ -z "$dns_redir_port" ] && dns_redir_port="$dns_port"
+[ -z "$fwmark" ] && fwmark="$redir_port"
+routing_mark=$((fwmark + 2))
+[ -z "$table" ] && table=100
+
+[ -z "$dns_nameserver" ] && {
+ dns_nameserver='223.5.5.5, 1.2.4.8'
+ cat /proc/net/udp | grep -q '0035' && dns_nameserver='localhost'
+}
+[ -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"
+ cat /proc/net/udp | grep -q '0035' && dns_resolver='127.0.0.1'
+}
\ No newline at end of file
diff --git a/scripts/libs/get_ecsip.sh b/scripts/libs/get_ecsip.sh
new file mode 100644
index 00000000..21cec0fa
--- /dev/null
+++ b/scripts/libs/get_ecsip.sh
@@ -0,0 +1,15 @@
+
+get_ecs_address() {
+ for f in /tmp/resolv.conf.auto /tmp/resolv.conf /tmp/resolv.conf.d/resolv.conf.auto; do
+ [ -f "$f" ] || continue
+ ip=$(grep -A1 "^# Interface wan$" "$f" | grep nameserver | awk '{printf "%s ", $2}')
+ [ -n "$ip" ] && return
+ done
+ . "$CRASHDIR"/libs/web_get_lite.sh
+ for web in http://members.3322.org/dyndns/getip http://4.ipw.cn http://ipinfo.io/ip; do
+ ip=$(web_get_lite "$web" 0)
+ [ -n "$ip" ] && return
+ done
+}
+get_ecs_address
+[ -n "$ip" ] && ecs_address="${ip%.*}.0/24"
diff --git a/scripts/libs/logger.sh b/scripts/libs/logger.sh
new file mode 100644
index 00000000..5d168ecb
--- /dev/null
+++ b/scripts/libs/logger.sh
@@ -0,0 +1,50 @@
+#日志工具
+. "$CRASHDIR"/libs/web_json.sh
+#$1日志内容$2显示颜色$3是否推送
+logger() {
+ TMPDIR=/tmp/ShellCrash
+ [ -n "$2" -a "$2" != 0 ] && echo -e "\033[$2m$1\033[0m"
+ log_text="$(date "+%G-%m-%d_%H:%M:%S")~$1"
+ echo "$log_text" >>"$TMPDIR"/ShellCrash.log
+ [ "$(wc -l "$TMPDIR"/ShellCrash.log | awk '{print $1}')" -gt 99 ] && sed -i '1,50d' "$TMPDIR"/ShellCrash.log
+ #推送远程日志
+ [ -z "$3" ] && {
+ [ -n "$device_name" ] && log_text="$log_text($device_name)"
+ [ -n "$push_TG" ] && {
+ url="https://api.telegram.org/bot${push_TG}/sendMessage"
+ [ "$push_TG" = 'publictoken' ] && url='https://tgbot.jwsc.eu.org/publictoken/sendMessage'
+ content="{\"chat_id\":\"${chat_ID}\",\"text\":\"$log_text\"}"
+ web_json_post "$url" "$content" &
+ }
+ [ -n "$push_bark" ] && {
+ url="${push_bark}"
+ content="{\"body\":\"${log_text}\",\"title\":\"ShellCrash日志推送\",\"level\":\"passive\",\"badge\":\"1\"}"
+ web_json_post "$url" "$content" &
+ }
+ [ -n "$push_Deer" ] && {
+ url="https://api2.pushdeer.com/message/push"
+ content="{\"pushkey\":\"${push_Deer}\",\"text\":\"$log_text\"}"
+ web_json_post "$url" "$content" &
+ }
+ [ -n "$push_Po" ] && {
+ url="https://api.pushover.net/1/messages.json"
+ content="{\"token\":\"${push_Po}\",\"user\":\"${push_Po_key}\",\"title\":\"ShellCrash日志推送\",\"message\":\"$log_text\"}"
+ web_json_post "$url" "$content" &
+ }
+ [ -n "$push_PP" ] && {
+ url="http://www.pushplus.plus/send"
+ content="{\"token\":\"${push_PP}\",\"title\":\"ShellCrash日志推送\",\"content\":\"$log_text\"}"
+ web_json_post "$url" "$content" &
+ }
+ [ -n "$push_Gotify" ] && {
+ url="${push_Gotify}"
+ content="{\"title\":\"ShellCrash日志推送\",\"message\":\"$log_text\",\"priority\":5}"
+ web_json_post "$url" "$content" &
+ }
+ [ -n "$push_SynoChat" ] && {
+ url="${push_ChatURL}/webapi/entry.cgi?api=SYNO.Chat.External&method=chatbot&version=2&token=${push_ChatTOKEN}"
+ content="payload={\"text\":\"${log_text}\", \"user_ids\":[${push_ChatUSERID}]}"
+ web_json_post "$url" "$content" &
+ }
+ } &
+}
diff --git a/scripts/libs/meta_listeners.sh b/scripts/libs/meta_listeners.sh
new file mode 100644
index 00000000..c338a769
--- /dev/null
+++ b/scripts/libs/meta_listeners.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+#meta内核vmess入站生成
+[ "$vms_service" = ON ] && {
+ cat >>"$TMPDIR"/listeners.yaml <>"$TMPDIR"/listeners.yaml <"$TMPDIR"/jsons/tailscale.json <"$TMPDIR"/jsons/wireguard.json <"$TMPDIR"/jsons/vmess-in.json <"$TMPDIR"/jsons/ss-in.json <>"$configpath"
+ fi
+}
\ No newline at end of file
diff --git a/scripts/libs/set_cron.sh b/scripts/libs/set_cron.sh
new file mode 100644
index 00000000..2af0d57d
--- /dev/null
+++ b/scripts/libs/set_cron.sh
@@ -0,0 +1,26 @@
+
+crondir="$(crond -h 2>&1 | grep -oE 'Default:.*' | awk -F ":" '{print $2}')"
+[ ! -w "$crondir" ] && crondir="/etc/storage/cron/crontabs"
+[ ! -w "$crondir" ] && crondir="/var/spool/cron/crontabs"
+[ ! -w "$crondir" ] && crondir="/var/spool/cron"
+tmpcron="$TMPDIR"/cron_tmp
+
+croncmd() { #定时任务工具
+ if [ -w "$crondir" ] && [ -n "$USER" ];then
+ [ "$1" = "-l" ] && cat "$crondir"/"$USER" 2>/dev/null
+ [ -f "$1" ] && cat "$1" >"$crondir"/"$USER"
+ elif [ -n "$(crontab -h 2>&1 | grep '\-l')" ]; then
+ crontab "$1"
+ else
+ echo "找不到可用的crond或者crontab应用!No available crond or crontab application can be found!"
+ fi
+}
+cronset() { #定时任务设置
+ # 参数1代表要移除的关键字,参数2代表要添加的任务语句
+ croncmd -l >"$tmpcron"
+ sed -i "/$1/d" "$tmpcron"
+ sed -i '/^$/d' "$tmpcron"
+ echo "$2" >>"$tmpcron"
+ croncmd "$tmpcron"
+ rm -f "$tmpcron"
+}
diff --git a/scripts/libs/set_profile.sh b/scripts/libs/set_profile.sh
new file mode 100644
index 00000000..2bf2790e
--- /dev/null
+++ b/scripts/libs/set_profile.sh
@@ -0,0 +1,8 @@
+
+set_profile() {
+ [ -z "$my_alias" ] && my_alias=crash
+ sed -i "/ShellCrash\/menu.sh/"d "$1"
+ echo "alias ${my_alias}=\"$shtype $CRASHDIR/menu.sh\"" >>"$1" #设置快捷命令环境变量
+ sed -i '/export CRASHDIR=*/'d "$1"
+ echo "export CRASHDIR=\"$CRASHDIR\"" >>"$1" #设置路径环境变量
+}
\ No newline at end of file
diff --git a/scripts/libs/set_proxy.sh b/scripts/libs/set_proxy.sh
new file mode 100644
index 00000000..3f3400cf
--- /dev/null
+++ b/scripts/libs/set_proxy.sh
@@ -0,0 +1,8 @@
+
+setproxy(){
+ [ -n "$(pidof CrashCore)" ] && {
+ [ -n "$authentication" ] && auth="$authentication@" || auth=""
+ [ -z "$mix_port" ] && mix_port=7890
+ export all_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
new file mode 100644
index 00000000..ffbee612
--- /dev/null
+++ b/scripts/libs/start_wait.sh
@@ -0,0 +1,10 @@
+i=1
+while [ -z "$test" -a "$i" -lt 30 ]; do
+ sleep 1
+ if curl --version >/dev/null 2>&1; then
+ test=$(curl -s -H "Authorization: Bearer $secret" http://127.0.0.1:${db_port}/proxies | grep -o proxies)
+ else
+ test=$(wget -q --header="Authorization: Bearer $secret" -O - http://127.0.0.1:${db_port}/proxies | grep -o proxies)
+ fi
+ i=$((i + 1))
+done
diff --git a/scripts/libs/urlencode.sh b/scripts/libs/urlencode.sh
new file mode 100644
index 00000000..abf4e8d8
--- /dev/null
+++ b/scripts/libs/urlencode.sh
@@ -0,0 +1,15 @@
+urlencode() {
+ LC_ALL=C
+ printf '%s' "$1" \
+ | hexdump -v -e '/1 "%02X\n"' \
+ | while read -r hex; do
+ case "$hex" in
+ 2D|2E|5F|7E|3[0-9]|4[1-9A-F]|5[0-9A]|6[1-9A-F]|7[0-9A-E])
+ printf "\\$(printf '%03o' "0x$hex")"
+ ;;
+ *)
+ printf "%%%s" "$hex"
+ ;;
+ esac
+ done
+}
\ No newline at end of file
diff --git a/scripts/libs/web_get.sh b/scripts/libs/web_get.sh
new file mode 100644
index 00000000..949fd6d9
--- /dev/null
+++ b/scripts/libs/web_get.sh
@@ -0,0 +1,48 @@
+. "$CRASHDIR"/libs/set_proxy.sh
+
+webget(){
+ if pidof CrashCore >/dev/null; then
+ setproxy #设置临时代理
+ url=$(printf '%s\n' "$2" |
+ sed -e 's#https://.*jsdelivr.net/gh/juewuy/ShellCrash[@|/]#https://raw.githubusercontent.com/juewuy/ShellCrash/#' \
+ -e 's#https://gh.jwsc.eu.org/#https://raw.githubusercontent.com/juewuy/ShellCrash/#')
+ else
+ url=$(printf '%s\n' "$2" |
+ sed 's#https://raw.githubusercontent.com/juewuy/ShellCrash/#https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@#')
+ fi
+ #参数【$1】代表下载目录,【$2】代表在线地址
+ #参数【$3】代表输出显示,【$4】不启用重定向
+ #参数【$5】代表验证证书,【$6】使用自定义UA
+ [ -n "$6" ] && agent="--user-agent \"$6\""
+ if wget --help 2>&1 | grep -q 'show-progress' >/dev/null 2>&1; then
+ [ "$3" = "echooff" ] && progress='-q' || progress='-q --show-progress'
+ [ "$4" = "rediroff" ] && redirect='--max-redirect=0' || redirect=''
+ [ "$5" = "skipceroff" ] && certificate='' || certificate='--no-check-certificate'
+ wget -Y on $agent $progress $redirect $certificate --timeout=3 -O "$1" "$url" && return 0 #成功则退出否则重试
+ wget -Y off $agent $progress $redirect $certificate --timeout=5 -O "$1" "$2"
+ return $?
+ elif curl --version >/dev/null 2>&1; then
+ [ "$3" = "echooff" ] && progress='-s' || progress='-#'
+ [ "$4" = "rediroff" ] && redirect='' || redirect='-L'
+ [ "$5" = "skipceroff" ] && certificate='' || certificate='-k'
+ if curl --version | grep -q '^curl 8.' && ckcmd base64; then
+ auth_b64=$(printf '%s' "$authentication" | base64)
+ result=$(curl $agent -w '%{http_code}' --connect-timeout 3 --proxy-header "Proxy-Authorization: Basic $auth_b64" $progress $redirect $certificate -o "$1" "$url")
+ else
+ result=$(curl $agent -w '%{http_code}' --connect-timeout 3 $progress $redirect $certificate -o "$1" "$url")
+ fi
+ [ "$result" = "200" ] && return 0 #成功则退出否则重试
+ export all_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 "找不到可用下载工具!!!请安装Curl或Wget!!!"
+ return 1
+ fi
+}
\ No newline at end of file
diff --git a/scripts/libs/web_get_bin.sh b/scripts/libs/web_get_bin.sh
new file mode 100644
index 00000000..c319519a
--- /dev/null
+++ b/scripts/libs/web_get_bin.sh
@@ -0,0 +1,18 @@
+. "$CRASHDIR"/libs/web_get.sh
+
+get_bin() { #专用于项目内部文件的下载
+ [ -z "$update_url" ] && update_url=https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master
+ if [ -n "$url_id" ]; then
+ [ -n "$release_type" ] && rt="$release_type" || rt=master
+ echo "$2" | grep -q '^bin/' && rt=update #/bin文件改为在update分支下载
+ echo "$2" | grep -qE '^public/|^rules/' && rt=dev #/public和/rules文件改为在dev分支下载
+ if [ "$url_id" = 101 -o "$url_id" = 104 ]; then
+ bin_url="$(grep "$url_id" "$CRASHDIR"/configs/servers.list | awk '{print $3}')@$rt/$2" #jsdelivr特殊处理
+ else
+ bin_url="$(grep "$url_id" "$CRASHDIR"/configs/servers.list | awk '{print $3}')/$rt/$2"
+ fi
+ else
+ bin_url="$update_url/$2"
+ fi
+ webget "$1" "$bin_url" "$3" "$4" "$5" "$6"
+}
\ No newline at end of file
diff --git a/scripts/libs/web_get_lite.sh b/scripts/libs/web_get_lite.sh
new file mode 100644
index 00000000..cf485b18
--- /dev/null
+++ b/scripts/libs/web_get_lite.sh
@@ -0,0 +1,10 @@
+. "$CRASHDIR"/libs/set_proxy.sh
+#$1:目标地址 $2:禁用proxy
+web_get_lite() {
+ [ -z "$2" ] && setproxy
+ if curl --version >/dev/null 2>&1; then
+ curl -ksSl --connect-timeout 3 "$1" 2>/dev/null
+ else
+ wget -Y on -q --timeout=3 -O - "$1"
+ fi
+}
diff --git a/scripts/libs/web_json.sh b/scripts/libs/web_json.sh
new file mode 100644
index 00000000..3c76260b
--- /dev/null
+++ b/scripts/libs/web_json.sh
@@ -0,0 +1,10 @@
+. "$CRASHDIR"/libs/set_proxy.sh
+#$1:目标地址 $2:json字符串
+web_json_post() {
+ setproxy
+ if curl --version >/dev/null 2>&1; then
+ curl -kfsSl -X POST --connect-timeout 3 -H "Content-Type: application/json" "$1" -d "$2" >/dev/null 2>&1
+ else
+ wget -Y on -q --timeout=3 --method=POST --header="Content-Type: application/json" --body-data="$2" "$1"
+ fi
+}
diff --git a/scripts/libs/web_restore.sh b/scripts/libs/web_restore.sh
new file mode 100644
index 00000000..e0368803
--- /dev/null
+++ b/scripts/libs/web_restore.sh
@@ -0,0 +1,20 @@
+
+#
+put_save() { #推送面板选择
+ [ -z "$3" ] && request_type=PUT || request_type=$3
+ if curl --version >/dev/null 2>&1; then
+ curl -sS -X "$request_type" -H "Authorization: Bearer $secret" -H "Content-Type:application/json" "$1" -d "$2" >/dev/null
+ elif wget --version >/dev/null 2>&1; then
+ wget -q --method="$request_type" --header="Authorization: Bearer $secret" --header="Content-Type:application/json" --body-data="$2" "$1" >/dev/null
+ fi
+}
+web_restore() { #还原面板选择
+ num=$(cat "$CRASHDIR"/configs/web_save | wc -l)
+ i=1
+ while [ "$i" -le "$num" ]; do
+ group_name=$(awk -F ',' 'NR=="'${i}'" {print $1}' "$CRASHDIR"/configs/web_save | sed 's/ /%20/g')
+ now_name=$(awk -F ',' 'NR=="'${i}'" {print $2}' "$CRASHDIR"/configs/web_save)
+ put_save "http://127.0.0.1:${db_port}/proxies/${group_name}" "{\"name\":\"${now_name}\"}"
+ i=$((i + 1))
+ done
+}
diff --git a/scripts/libs/web_save.sh b/scripts/libs/web_save.sh
new file mode 100644
index 00000000..b9f75c88
--- /dev/null
+++ b/scripts/libs/web_save.sh
@@ -0,0 +1,30 @@
+
+#
+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 web_configs; do
+ if [ -s "$TMPDIR"/${file} ]; then
+ . "$CRASHDIR"/libs/compare.sh && compare "$TMPDIR"/${file} "$CRASHDIR"/configs/${file}
+ [ "$?" = 0 ] && rm -rf "$TMPDIR"/${file} || mv -f "$TMPDIR"/${file} "$CRASHDIR"/configs/${file}
+ fi
+ done
+}
diff --git a/scripts/menu.sh b/scripts/menu.sh
index 4e03d412..86dac1e0 100644
--- a/scripts/menu.sh
+++ b/scripts/menu.sh
@@ -5,50 +5,54 @@ CRASHDIR=$(
cd $(dirname $0)
pwd
)
-CFG_PATH=${CRASHDIR}/configs/ShellCrash.cfg
-YAMLSDIR=${CRASHDIR}/yamls
-JSONSDIR=${CRASHDIR}/jsons
+CFG_PATH="$CRASHDIR"/configs/ShellCrash.cfg
#加载执行目录,失败则初始化
-. ${CRASHDIR}/configs/command.env 2>/dev/null
-[ -z "$BINDIR" -o -z "$TMPDIR" -o -z "$COMMAND" ] && . ${CRASHDIR}/init.sh >/dev/null 2>&1
-[ ! -f ${TMPDIR} ] && mkdir -p ${TMPDIR}
-[ -n "$(tar --help 2>&1 | grep -o 'no-same-owner')" ] && tar_para='--no-same-owner' #tar命令兼容
+. "$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"
-#读取配置相关
-setconfig() {
- #参数1代表变量名,参数2代表变量值,参数3即文件路径
- [ -z "$3" ] && configpath="$CRASHDIR"/configs/ShellCrash.cfg || configpath="${3}"
- if grep -q "^${1}=" "$configpath"; then
- sed -i "s#^${1}=.*#${1}=${2}#g" "$configpath"
- else
- printf '%s=%s\n' "$1" "$2" >>"$configpath"
- fi
+#通用工具
+. "$CRASHDIR"/libs/set_config.sh
+. "$CRASHDIR"/libs/check_cmd.sh
+. "$CRASHDIR"/libs/check_autostart.sh
+. "$CRASHDIR"/menus/1_start.sh
+. "$CRASHDIR"/menus/running_status.sh
+errornum() {
+ echo "-----------------------------------------------"
+ echo -e "\033[31m请输入正确的字母或数字!\033[0m"
}
-ckcmd() {
- command -v sh >/dev/null 2>&1 && command -v $1 >/dev/null 2>&1 || type $1 >/dev/null 2>&1
+checkrestart() {
+ echo "-----------------------------------------------"
+ echo -e "\033[32m检测到已变更的内容,请重启服务!\033[0m"
+ echo "-----------------------------------------------"
+ read -p "是否现在重启服务?(1/0) > " res
+ [ "$res" = 1 ] && start_service
}
-#脚本启动前检查
-ckstatus() {
- #检查/读取脚本配置文件
- if [ -f $CFG_PATH ]; then
- [ -n "$(awk 'a[$0]++' $CFG_PATH)" ] && awk '!a[$0]++' $CFG_PATH >$CFG_PATH #检查重复行并去除
- . $CFG_PATH 2>/dev/null
+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"
+ . "$CRASHDIR"/menus/2_settings.sh && set_adv_config
+ . "$CRASHDIR"/libs/get_config.sh
+ checkport
+ fi
+ done
+}
+ckstatus() { #脚本启动前检查
+ #检查脚本配置文件
+ if [ -f "$CFG_PATH" ]; then
+ [ -n "$(awk 'a[$0]++' $CFG_PATH)" ] && awk '!a[$0]++' "$CFG_PATH" >"$CFG_PATH" #检查重复行并去除
else
- . ${CRASHDIR}/init.sh >/dev/null 2>&1
+ . "$CRASHDIR"/init.sh >/dev/null 2>&1
fi
versionsh=$(cat "$CRASHDIR"/version)
[ -n "$versionsh" ] && versionsh_l=$versionsh
- #服务器缺省地址
- [ -z "$mix_port" ] && mix_port=7890
- [ -z "$redir_port" ] && redir_port=7892
- [ -z "$fwmark" ] && fwmark=$redir_port
- [ -z "$db_port" ] && db_port=9999
- [ -z "$dns_port" ] && dns_port=1053
- [ -z "$multiport" ] && multiport='22,80,143,194,443,465,587,853,993,995,5222,8080,8443'
[ -z "$redir_mod" ] && redir_mod=纯净模式
- #检查mac地址记录
- [ ! -f ${CRASHDIR}/configs/mac ] && touch ${CRASHDIR}/configs/mac
#获取本机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)
@@ -59,23 +63,11 @@ ckstatus() {
dbdir=/www/clash
hostdir=/clash
else
- dbdir=${CRASHDIR}/ui
+ dbdir="$CRASHDIR"/ui
hostdir=":$db_port/ui"
fi
#开机自启检测
- if [ -f /etc/rc.common -a "$(cat /proc/1/comm)" = "procd" ]; then
- [ -n "$(find /etc/rc.d -name '*shellcrash')" ] && autostart=enable || autostart=disable
- elif ckcmd systemctl; then
- [ "$(systemctl is-enabled shellcrash.service 2>&1)" = enabled ] && autostart=enable || autostart=disable
- elif grep -q 's6' /proc/1/comm; then
- [ -f /etc/s6-overlay/s6-rc.d/user/contents.d/afstart ] && autostart=enable || autostart=disable
- elif rc-status -r >/dev/null 2>&1; then
- rc-update show default | grep -q "shellcrash" && autostart=enable || autostart=disable
- else
- [ -f ${CRASHDIR}/.dis_startup ] && autostart=disable || autostart=enable
- fi
- #开机自启描述
- if [ "$autostart" = "enable" ]; then
+ if check_autostart; then
auto="\033[32m已设置开机启动!\033[0m"
auto1="\033[36m禁用\033[0mShellCrash开机启动"
else
@@ -86,16 +78,7 @@ ckstatus() {
PID=$(pidof CrashCore | awk '{print $NF}')
if [ -n "$PID" ]; then
run="\033[32m正在运行($redir_mod)\033[0m"
- 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
+ running_status
elif [ "$firewall_area" = 5 ] && [ -n "$(ip route list table 100)" ]; then
run="\033[32m已设置($redir_mod)\033[0m"
else
@@ -105,11 +88,11 @@ ckstatus() {
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"
+ [ -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""
+ 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
@@ -118,47 +101,40 @@ ckstatus() {
#检查新手引导
if [ -z "$userguide" ]; then
setconfig userguide 1
- . ${CRASHDIR}/webget.sh && userguide
+ . "$CRASHDIR"/menus/8_tools.sh && userguide
fi
#检查执行权限
- [ ! -x ${CRASHDIR}/start.sh ] && chmod +x ${CRASHDIR}/start.sh
+ [ ! -x "$CRASHDIR"/start.sh ] && chmod +x "$CRASHDIR"/start.sh
#检查/tmp内核文件
- for file in $(ls /tmp | grep -v [/$] | grep -v ' ' | grep -Ev ".*(gz|zip|7z|tar)$" | grep -iE 'CrashCore|^clash$|^clash-linux.*|^mihomo.*|^sing.*box|meta.*'); do
- chmod +x /tmp/$file
+ for file in $(ls /tmp | grep -v [/$] | grep -v ' ' | grep -Ev ".*(zip|7z|tar)$" | grep -iE 'CrashCore|^clash$|^clash-linux.*|^mihomo.*|^sing.*box|meta.*'); do
echo -e "发现可用的内核文件: \033[36m/tmp/$file\033[0m "
read -p "是否加载(会停止当前服务)?(1/0) > " res
[ "$res" = 1 ] && {
- ${CRASHDIR}/start.sh stop
- core_v=$(/tmp/$file -v 2>/dev/null | head -n 1 | sed 's/ linux.*//;s/.* //')
- [ -z "$core_v" ] && core_v=$(/tmp/$file version 2>/dev/null | grep -Eo 'version .*' | sed 's/version //')
- if [ -n "$core_v" ]; then
- . ${CRASHDIR}/webget.sh && setcoretype &&
- mv -f /tmp/$file ${TMPDIR}/CrashCore &&
- tar -zcf ${BINDIR}/CrashCore.tar.gz ${tar_para} -C ${TMPDIR} CrashCore &&
- echo -e "\033[32m内核加载完成!\033[0m " &&
- setconfig crashcore $crashcore &&
- setconfig core_v $core_v &&
- switch_core
- sleep 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
else
echo -e "\033[33m检测到不可用的内核文件!可能是文件受损或CPU架构不匹配!\033[0m"
- rm -rf /tmp/$file
- echo -e "\033[33m内核文件已移除,请认真检查后重新上传!\033[0m"
- sleep 2
+ rm -rf /tmp/"$file"
+ echo -e "\033[33m内核文件已移除,请认真检查后重新上传!\033[0m"
fi
+ sleep 1
}
echo "-----------------------------------------------"
done
#检查/tmp配置文件
- for file in $(ls /tmp | grep -v [/$] | grep -v ' ' | grep -iE '.yaml$|.yml$|config.json$'); do
+ 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
[ "$res" = 1 ] && {
if [ -n "$(echo /tmp/$file | grep -iE '.json$')" ]; then
- mv -f /tmp/$file ${CRASHDIR}/jsons/config.json
+ 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
@@ -173,2069 +149,20 @@ ckstatus() {
}
}
-errornum() {
- echo "-----------------------------------------------"
- echo -e "\033[31m请输入正确的字母或数字!\033[0m"
-}
-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}"
- fi
- return 0
-}
-start_core() {
- if echo "$crashcore" | grep -q 'singbox'; then
- core_config=${CRASHDIR}/jsons/config.json
- else
- core_config=${CRASHDIR}/yamls/config.yaml
- fi
- 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}/webget.sh && gen_${coretype}_providers
- elif [ -s $core_config -o -n "$Url" -o -n "$Https" ]; then
- ${CRASHDIR}/start.sh start
- #设置循环检测以判定服务启动是否成功
- 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}/configs | grep -o port)
- else
- test=$(wget -q --header="Authorization: Bearer $secret" -O - http://127.0.0.1:${db_port}/configs | grep -o port)
- fi
- i=$((i + 1))
- done
- [ -n "$test" -o -n "$(pidof CrashCore)" ] && startover
- else
- echo -e "\033[31m没有找到${crashcore}配置文件,请先导入配置文件!\033[0m"
- . ${CRASHDIR}/webget.sh && set_core_config
- fi
-}
-start_service() {
- if [ "$firewall_area" = 5 ]; then
- ${CRASHDIR}/start.sh start
- echo -e "\033[32m已完成防火墙设置!\033[0m"
- else
- start_core
- fi
-}
-checkrestart() {
- echo "-----------------------------------------------"
- echo -e "\033[32m检测到已变更的内容,请重启服务!\033[0m"
- echo "-----------------------------------------------"
- read -p "是否现在重启服务?(1/0) > " res
- [ "$res" = 1 ] && start_service
-}
-#功能相关
-log_pusher() { #日志菜单
- [ -n "$push_TG" ] && stat_TG=32m已启用 || stat_TG=33m未启用
- [ -n "$push_Deer" ] && stat_Deer=32m已启用 || stat_Deer=33m未启用
- [ -n "$push_bark" ] && stat_bark=32m已启用 || stat_bark=33m未启用
- [ -n "$push_Po" ] && stat_Po=32m已启用 || stat_Po=33m未启用
- [ -n "$push_PP" ] && stat_PP=32m已启用 || stat_PP=33m未启用
- [ -n "$push_SynoChat" ] && stat_SynoChat=32m已启用 || stat_SynoChat=33m未启用
- [ -n "$push_Gotify" ] && stat_Gotify=32m已启用 || stat_Gotify=33m未启用
- [ "$task_push" = 1 ] && stat_task=32m已启用 || stat_task=33m未启用
- [ -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 "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- a)
- if [ -s ${TMPDIR}/ShellCrash.log ]; then
- echo "-----------------------------------------------"
- cat ${TMPDIR}/ShellCrash.log
- exit 0
- else
- echo -e "\033[31m未找到相关日志!\033[0m"
- fi
- sleep 1
- ;;
- 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"
- private_bot() {
- 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
- }
- set_bot() {
- echo -e "发送此秘钥: \033[30;46m$public_key\033[0m"
- echo "-----------------------------------------------"
- read -p "我已经发送完成(1/0) > " res
- if [ "$res" = 1 ]; then
- [ -n "$authentication" ] && auth="$authentication@"
- export https_proxy="http://${auth}127.0.0.1:$mix_port"
- if curl --version >/dev/null 2>&1; then
- chat=$(curl -kfsSl $url_tg 2>/dev/null)
- else
- chat=$(wget -Y on -q -O - $url_tg)
- fi
- [ -n "$chat" ] && 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//')
- [ -z "$chat_ID" ] && {
- 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
- push_TG=$TOKEN
- setconfig push_TG $TOKEN
- setconfig chat_ID $chat_ID
- ${CRASHDIR}/start.sh logger "已完成Telegram日志推送设置!" 32
- else
- echo -e "\033[31m无法获取对话ID,请重新配置!\033[0m"
- sleep 1
- chose_bot
- fi
- fi
- }
- chose_bot() {
- public_key=$(cat /proc/sys/kernel/random/boot_id | sed 's/.*-//')
- echo "-----------------------------------------------"
- echo -e " 1 使用公共机器人 ——不依赖内核服务"
- echo -e " 2 使用私人机器人 ——需要额外申请"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case $num in
- 1)
- public_bot
- set_bot
- ;;
- 2)
- private_bot
- set_bot
- ;;
- *)
- errornum
- ;;
- esac
- }
- chose_bot
- fi
- sleep 1
- log_pusher
- ;;
- 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
- ${CRASHDIR}/start.sh logger "已完成PushDeer日志推送设置!" 32
- else
- echo -e "\033[31m输入错误,请重新输入!\033[0m"
- fi
- sleep 1
- fi
- log_pusher
- ;;
- 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
- ${CRASHDIR}/start.sh logger "已完成Bark日志推送设置!" 32
- else
- echo -e "\033[31m输入错误,请重新输入!\033[0m"
- fi
- sleep 1
- fi
- log_pusher
- ;;
- 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
- ${CRASHDIR}/start.sh logger "已完成Passover日志推送设置!" 32
- else
- echo -e "\033[31m输入错误,请重新输入!\033[0m"
- fi
- else
- echo -e "\033[31m输入错误,请重新输入!\033[0m"
- fi
- fi
- sleep 1
- log_pusher
- ;;
- 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
- ${CRASHDIR}/start.sh logger "已完成PushPlus日志推送设置!" 32
- else
- echo -e "\033[31m输入错误,请重新输入!\033[0m"
- fi
- fi
- sleep 1
- log_pusher
- ;;
- 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
- ${CRASHDIR}/start.sh 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
- log_pusher
- ;;
- # 在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"
- ${CRASHDIR}/start.sh logger "已完成Gotify日志推送设置!" 32
- else
- echo -e "\033[31m输入错误,请重新输入!\033[0m"
- fi
- fi
- sleep 1
- log_pusher
- ;;
- b)
- [ "$task_push" = 1 ] && task_push='' || task_push=1
- setconfig task_push $task_push
- sleep 1
- log_pusher
- ;;
- c)
- read -p "请输入本设备自定义推送名称 > " device_name
- setconfig device_name $device_name
- sleep 1
- log_pusher
- ;;
- d)
- echo -e "\033[33m运行日志及任务日志均已清空!\033[0m"
- rm -rf ${TMPDIR}/ShellCrash.log
- sleep 1
- log_pusher
- ;;
- *) errornum ;;
- esac
-}
-setport() { #端口设置
- . $CFG_PATH >/dev/null
- [ -z "$secret" ] && secret=未设置
- [ -z "$table" ] && table=100
- [ -z "$authentication" ] && auth=未设置 || auth=******
- inputport() {
- read -p "请输入端口号(1-65535) > " portx
- if [ -z "$portx" ]; then
- setport
- elif [ $portx -gt 65535 -o $portx -le 1 ]; then
- echo -e "\033[31m输入错误!请输入正确的数值(1-65535)!\033[0m"
- inputport
- elif [ -n "$(echo "|$mix_port|$redir_port|$dns_port|$db_port|" | grep "|$portx|")" ]; then
- echo -e "\033[31m输入错误!请不要输入重复的端口!\033[0m"
- inputport
- elif [ -n "$(netstat -ntul | grep ":$portx ")" ]; then
- echo -e "\033[31m当前端口已被其他进程占用,请重新输入!\033[0m"
- inputport
- else
- setconfig $xport $portx
- echo -e "\033[32m设置成功!!!\033[0m"
- setport
- 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 " 7 修改默认端口过滤: \033[36m$multiport\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" = "已开启" -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"
- else
- echo -e "\033[31m输入有误,请重新输入!\033[0m"
- fi
- fi
- fi
- setport
- ;;
- 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
- setport
- ;;
- 7)
- echo "-----------------------------------------------"
- echo -e "需配合\033[32m仅代理常用端口\033[0m功能使用"
- echo -e "多个端口请用小写逗号分隔,例如:\033[33m143,80,443\033[0m"
- echo -e "输入 0 重置为默认端口"
- echo "-----------------------------------------------"
- read -p "请输入需要指定代理的端口 > " multiport
- if [ -n "$multiport" ]; then
- [ "$multiport" = "0" ] && multiport="22,80,143,194,443,465,587,853,993,995,5222,8080,8443"
- common_ports=已开启
- setconfig multiport $multiport
- setconfig common_ports $common_ports
- echo -e "\033[32m设置成功!!!\033[0m"
- fi
- setport
- ;;
- 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"
- 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
- setport
- ;;
- 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
- setport
- ;;
- *)
- errornum
- ;;
- esac
-}
-setdns() { #DNS详细设置
- [ -z "$dns_nameserver" ] && dns_nameserver='223.5.5.5, 1.2.4.8'
- [ -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 "$hosts_opt" ] && hosts_opt=已启用
- [ -z "$dns_protect" ] && dns_protect=ON
- [ -z "$dns_redir" ] && dns_redir=未开启
- [ -z "$dns_no" ] && dns_no=未禁用
- 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 DNS防泄漏: \033[36m$dns_protect\033[0m ———启用时少量网站可能连接卡顿"
- echo -e " 5 hosts优化: \033[36m$hosts_opt\033[0m ———调用本机hosts并劫持NTP服务"
- #echo -e " 6 Dnsmasq转发:\033[36m$dns_redir\033[0m ———不推荐使用"
- echo -e " 7 禁用DNS劫持:\033[36m$dns_no\033[0m ———搭配第三方DNS使用"
- echo -e " 8 一键配置\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
- setdns
- ;;
- 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
- setdns
- ;;
- 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
- setdns
- ;;
- 4)
- [ "$dns_protect" = "ON" ] && dns_protect=OFF || dns_protect=ON
- setconfig dns_protect $dns_protect
- setdns
- ;;
- 5)
- echo "-----------------------------------------------"
- if [ "$hosts_opt" = "已启用" ]; then
- hosts_opt=未启用
- echo -e "\033[32m已禁用hosts优化功能!!!\033[0m"
- else
- hosts_opt=已启用
- echo -e "\033[33m已启用hosts优化功能!!!\033[0m"
- fi
- setconfig hosts_opt $hosts_opt
- sleep 1
- setdns
- ;;
- 6)
- echo "-----------------------------------------------"
- if [ "$dns_redir" = "未开启" ]; then
- echo -e "\033[31m将使用OpenWrt中Dnsmasq插件自带的DNS转发功能转发DNS请求至内核!\033[0m"
- echo -e "\033[33m启用后将禁用本插件自带的iptables转发功能\033[0m"
- dns_redir=已开启
- echo -e "\033[32m已启用Dnsmasq转发DNS功能!!!\033[0m"
- else
- uci del dhcp.@dnsmasq[-1].server
- uci set dhcp.@dnsmasq[0].noresolv=0
- uci commit dhcp
- /etc/init.d/dnsmasq restart
- echo -e "\033[33m禁用成功!!如有报错请重启设备!\033[0m"
- dns_redir=未开启
- fi
- setconfig dns_redir $dns_redir
- sleep 1
- setdns
- ;;
- 7)
- echo "-----------------------------------------------"
- if [ "$dns_no" = "未禁用" ]; then
- echo -e "\033[31m仅限搭配其他DNS服务(比如dnsmasq、smartDNS)时使用!\033[0m"
- dns_no=已禁用
- echo -e "\033[32m已禁用DNS劫持!!!\033[0m"
- else
- dns_no=未禁用
- echo -e "\033[33m已启用DNS劫持!!!\033[0m"
- fi
- setconfig dns_no $dns_no
- sleep 1
- setdns
- ;;
- 8)
- 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
- setdns
- ;;
- 9)
- dns_nameserver=
- dns_fallback=
- dns_resolver=
- setconfig dns_nameserver
- setconfig dns_fallback
- setconfig dns_resolver
- echo -e "\033[33mDNS配置已重置!!!\033[0m"
- sleep 1
- setdns
- ;;
- *)
- errornum
- sleep 1
- ;;
- esac
-}
-setipv6() { #ipv6设置
- [ -z "$ipv6_redir" ] && ipv6_redir=未开启
- [ -z "$ipv6_dns" ] && ipv6_dns=已开启
- [ -z "$cn_ipv6_route" ] && cn_ipv6_route=未开启
- 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 " 3 CNV6绕过内核: \033[36m$cn_ipv6_route\033[0m ——优化性能,不兼容fake-ip"
- echo -e " 0 返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0) ;;
- 1)
- if [ "$ipv6_redir" = "未开启" ]; then
- ipv6_support=已开启
- ipv6_redir=已开启
- sleep 2
- else
- ipv6_redir=未开启
- fi
- setconfig ipv6_redir $ipv6_redir
- setconfig ipv6_support $ipv6_support
- setipv6
- ;;
- 2)
- [ "$ipv6_dns" = "未开启" ] && ipv6_dns=已开启 || ipv6_dns=未开启
- setconfig ipv6_dns $ipv6_dns
- setipv6
- ;;
- 3)
- if [ "$ipv6_redir" = "未开启" ]; then
- ipv6_support=已开启
- ipv6_redir=已开启
- setconfig ipv6_redir $ipv6_redir
- setconfig ipv6_support $ipv6_support
- fi
- if [ -n "$(ipset -v 2>/dev/null)" ] || [ "$firewall_mod" = nftables ]; then
- [ "$cn_ipv6_route" = "未开启" ] && cn_ipv6_route=已开启 || cn_ipv6_route=未开启
- setconfig cn_ipv6_route $cn_ipv6_route
- else
- echo -e "\033[31m当前设备缺少ipset模块或防火墙未使用nftables,无法启用绕过功能!!\033[0m"
- sleep 1
- fi
- setipv6
- ;;
- *)
- errornum
- ;;
- esac
-}
-setfirewall() { #防火墙设置
- set_cust_host_ipv4() {
- [ -z "$replace_default_host_ipv4" ] && replace_default_host_ipv4="未启用"
-
- echo "-----------------------------------------------"
- echo -e "当前默认透明路由的网段为: \033[32m$(ip a 2>&1 | grep -w 'inet' | grep 'global' | grep 'br' | grep -v 'iot' | grep -E ' 1(92|0|72)\.' | sed 's/.*inet.//g' | sed 's/br.*$//g' | sed 's/metric.*$//g' | tr '\n' ' ' && echo) \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" == "未启用" ]; then
- replace_default_host_ipv4="已启用"
- else
- replace_default_host_ipv4="未启用"
- 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
- }
- [ -z "$public_support" ] && public_support=未开启
- [ -z "$public_mixport" ] && public_mixport=未开启
- [ -z "$ipv6_dns" ] && ipv6_dns=已开启
- [ -z "$cn_ipv6_route" ] && cn_ipv6_route=未开启
- echo "-----------------------------------------------"
- echo -e " 1 公网访问Dashboard面板: \033[36m$public_support\033[0m"
- echo -e " 2 公网访问Socks/Http代理: \033[36m$public_mixport\033[0m"
- echo -e " 3 自定义透明路由ipv4网段: 适合vlan等复杂网络环境"
- echo -e " 4 自定义保留地址ipv4网段: 需要以保留地址为访问目标的环境"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- 1)
- if [ "$public_support" = "未开启" ]; then
- public_support=已开启
- else
- public_support=未开启
- fi
- setconfig public_support $public_support
- setfirewall
- ;;
- 2)
- if [ "$public_mixport" = "未开启" ]; then
- if [ "$mix_port" = "7890" -o -z "$authentication" ]; then
- echo "-----------------------------------------------"
- echo -e "\033[33m为了安全考虑,请先修改默认Socks/Http端口并设置代理密码\033[0m"
- sleep 1
- setport
- else
- public_mixport=已开启
- fi
- else
- public_mixport=未开启
- fi
- setconfig public_mixport $public_mixport
- setfirewall
- ;;
- 3)
- set_cust_host_ipv4
- setfirewall
- ;;
- 4)
- [ -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
- setfirewall
- ;;
- *)
- errornum
- ;;
- esac
-}
-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"
- setport
- . $CFG_PATH >/dev/null
- checkport
- fi
- done
-}
-macfilter() { #局域网设备过滤
- 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
- macfilter_over='白名单'
- macfilter_scrip='不'
- else
- macfilter_over='黑名单'
- macfilter_scrip=''
- fi
- ######
- echo -e "\033[30;47m请在此添加或移除设备\033[0m"
- echo -e "当前过滤方式为:\033[33m$macfilter_type模式\033[0m"
- echo -e "仅列表内设备流量\033[36m$macfilter_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$macfilter_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=$macfilter_over
- setconfig macfilter_type $macfilter_type
- echo "-----------------------------------------------"
- echo -e "\033[32m已切换为$macfilter_type模式!\033[0m"
- macfilter
- ;;
- 2)
- add_mac
- macfilter
- ;;
- 3)
- add_ip
- macfilter
- ;;
- 4)
- del_all
- macfilter
- ;;
- 9)
- : >${CRASHDIR}/configs/mac
- : >${CRASHDIR}/configs/ip_filter
- echo "-----------------------------------------------"
- echo -e "\033[31m设备列表已清空!\033[0m"
- macfilter
- ;;
- *)
- errornum
- ;;
- esac
-}
-setboot() { #启动相关设置
- [ -z "$start_old" ] && start_old=未开启
- [ -z "$start_delay" -o "$start_delay" = 0 ] && delay=未设置 || delay=${start_delay}秒
- [ "$autostart" = "enable" ] && auto_set="\033[33m禁止" || auto_set="\033[32m允许"
- [ "${BINDIR}" = "${CRASHDIR}" ] && mini_clash=未开启 || mini_clash=已开启
- [ -z "$network_check" ] && network_check=已开启
- 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 "-----------------------------------------------"
- case "$num" in
- 0) ;;
- 1)
- if [ "$autostart" = "enable" ]; then
- # 禁止自启动:删除各系统的启动项
- [ -d /etc/rc.d ] && cd /etc/rc.d && rm -rf *shellcrash >/dev/null 2>&1 && cd - >/dev/null
- ckcmd systemctl && systemctl disable shellcrash.service >/dev/null 2>&1
- grep -q 's6' /proc/1/comm && rm -rf /etc/s6-overlay/s6-rc.d/user/contents.d/afstart
- rc-status -r >/dev/null 2>&1 && rc-update del shellcrash default >/dev/null 2>&1
- touch ${CRASHDIR}/.dis_startup
- autostart=disable
- echo -e "\033[33m已禁止ShellCrash开机启动!\033[0m"
- elif [ "$autostart" = "disable" ]; then
- # 允许自启动:配置各系统的启动项
- [ -f /etc/rc.common -a "$(cat /proc/1/comm)" = "procd" ] && /etc/init.d/shellcrash enable
- ckcmd systemctl && systemctl enable shellcrash.service >/dev/null 2>&1
- grep -q 's6' /proc/1/comm && touch /etc/s6-overlay/s6-rc.d/user/contents.d/afstart
- rc-status -r >/dev/null 2>&1 && rc-update add shellcrash default >/dev/null 2>&1
- rm -rf ${CRASHDIR}/.dis_startup
- autostart=enable
- echo -e "\033[32m已设置ShellCrash开机启动!\033[0m"
- fi
- setboot
- ;;
- 2)
- if [ "$start_old" = "未开启" ] >/dev/null 2>&1; then
- echo -e "\033[33m改为使用保守模式启动服务!!\033[0m"
- [ -d /etc/rc.d ] && cd /etc/rc.d && rm -rf *shellcrash >/dev/null 2>&1 && cd - >/dev/null
- ckcmd systemctl && systemctl disable shellcrash.service >/dev/null 2>&1
- grep -q 's6' /proc/1/comm && rm -rf /etc/s6-overlay/s6-rc.d/user/contents.d/afstart
- rc-status -r >/dev/null 2>&1 && rc-update del shellcrash default >/dev/null 2>&1
- start_old=已开启
- setconfig start_old $start_old
- ${CRASHDIR}/start.sh stop
- 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初始化"
- start_old=未开启
- setconfig start_old $start_old
- ${CRASHDIR}/start.sh stop
-
- else
- echo -e "\033[31m当前设备不支持以其他模式启动!!\033[0m"
- fi
- fi
- sleep 1
- setboot
- ;;
- 3)
- echo -e "\033[33m如果你的设备启动后可以正常使用,则无需设置!!\033[0m"
- echo -e "\033[36m推荐设置为30~120秒之间,请根据设备问题自行试验\033[0m"
- read -p "请输入启动延迟时间(0~300秒) > " 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"
- ;;
- *)
- echo -e "\033[31m输入有误,或超过300秒,请重新输入!\033[0m"
- ;;
- esac
- sleep 1
- setboot
- ;;
- 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" = "未开启" ]; then
- if [ "$dir_size" -gt 20480 ]; then
- echo -e "\033[33m您的设备空间充足(>20M),无需开启!\033[0m"
- elif [ "$start_old" != '已开启' -a "$(cat /proc/1/comm)" = "systemd" ]; then
- echo -e "\033[33m不支持systemd启动模式,请先启用保守模式!\033[0m"
- else
- [ "$BINDIR" = "$CRASHDIR" ] && BINDIR="$TMPDIR"
- echo -e "\033[32m已经启用小闪存功能!\033[0m"
- echo -e "如需更换目录,请使用【设置小闪存目录】功能\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"
- else
- rm -rf /tmp/ShellCrash
- BINDIR="$CRASHDIR"
- echo -e "\033[33m已经停用小闪存功能!\033[0m"
- fi
- fi
- setconfig BINDIR ${BINDIR} ${CRASHDIR}/configs/command.env
- sleep 1
- setboot
- ;;
- 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
- fi
- }
- set_usb_dir
- ;;
- 3)
- input_dir() {
- read -p "请输入自定义目录 > " BINDIR
- if [ ! -d "$BINDIR" ]; then
- echo "\033[31m输入错误!请重新设置!\033[0m"
- input_dir
- fi
- }
- input_dir
- ;;
- *)
- errornum
- ;;
- esac
- setconfig BINDIR ${BINDIR} ${CRASHDIR}/configs/command.env
- setboot
- ;;
- 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' ] && {
- if [ "$network_check" = "已禁用" ]; then
- network_check=已启用
- else
- network_check=已禁用
- fi
- setconfig network_check $network_check
- }
- sleep 1
- setboot
- ;;
- *)
- errornum
- ;;
- esac
-
-}
-set_firewall_area() { #防火墙模式设置
- [ -z "$vm_redir" ] && vm_redir='未开启'
- echo "-----------------------------------------------"
- echo -e "\033[31m注意:\033[0m基于桥接网卡的Docker/虚拟机流量,请单独启用6!"
- 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 " 6 劫持容器/虚拟机流量: \033[36m$vm_redir\033[0m"
- echo -e " 0 返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " 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
- }
- ;;
- 6)
- 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=已开启
- 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=已开启
- ;;
- 3)
- vm_redir=未开启
- unset vm_ipv4
- ;;
- *) ;;
- esac
- setconfig vm_redir $vm_redir
- setconfig vm_ipv4 "'$vm_ipv4'"
- sleep 1
- set_firewall_area
- ;;
- *) errornum ;;
- esac
- sleep 1
-}
-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 && 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$firewall_mod\033[0m"
- echo -e " 9 ipv6设置:\033[47;30m$ipv6_redir\033[0m"
- 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' ] && {
- ${CRASHDIR}/misnap_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)
- 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
- ;;
- 9)
- setipv6
- set_redir_mod
- ;;
- *)
- errornum
- ;;
- esac
-}
-set_dns_mod() { #DNS模式设置
- echo "-----------------------------------------------"
- echo -e "当前DNS运行模式为:\033[47;30m $dns_mod \033[0m"
- echo -e "\033[33m切换模式后需要手动重启服务以生效!\033[0m"
- echo "-----------------------------------------------"
- echo -e " 1 fake-ip模式: 响应快,\033[33m兼容性较差\033[0m"
- echo -e " 不支持CN-IP绕过功能"
- echo -e " 2 redir_host模式:\033[33m不安全,易被污染\033[0m"
- echo -e " 建议搭配第三方DNS服务使用"
- if echo "$crashcore" | grep -q 'singbox' || [ "$crashcore" = meta ]; then
- echo -e " 3 mix混合模式: \033[32m防污染防泄露,响应快,推荐!\033[0m"
- echo -e " cn域名realip其他fakeip分流"
- echo -e " 4 route模式: \033[32m防污染防泄露,全真实IP\033[0m"
- echo -e " cn域名realip其他dns2proxy分流"
- fi
- echo -e " 9 \033[36mDNS进阶设置\033[0m"
- echo " 0 返回上级菜单"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0) ;;
- 1)
- dns_mod=fake-ip
- setconfig dns_mod $dns_mod
- echo "-----------------------------------------------"
- echo -e "\033[36m已设为 $dns_mod 模式!!\033[0m"
- ;;
- 2)
- dns_mod=redir_host
- setconfig dns_mod $dns_mod
- echo "-----------------------------------------------"
- echo -e "\033[36m已设为 $dns_mod 模式!!\033[0m"
- ;;
- 3)
- 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
- ;;
- 4)
- 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
- ;;
- 9)
- setdns
- set_dns_mod
- ;;
- *)
- errornum
- ;;
- esac
-}
-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"
- else
- echo -e "你输入的地址是:\033[32m$input\033[0m"
- read -p "确认添加?(1/0) > " res
- [ "$res" = 1 ] && echo $input >>${CRASHDIR}/configs/fake_ip_filter
- fi
- sleep 1
- fake_ip_filter
- ;;
- esac
-}
-normal_set() { #基础设置
- #获取设置默认显示
- [ -z "$skip_cert" ] && skip_cert=已开启
- [ -z "$common_ports" ] && common_ports=已开启
- [ -z "$dns_mod" ] && dns_mod=fake-ip
- [ -z "$dns_over" ] && dns_over=已开启
- [ -z "$cn_ip_route" ] && cn_ip_route=未开启
- [ -z "$local_proxy" ] && local_proxy=未开启
- [ -z "$quic_rj" ] && quic_rj=未开启
- [ -z "$(cat ${CRASHDIR}/configs/mac ${CRASHDIR}/configs/ip_filter 2>/dev/null)" ] && mac_return=未开启 || mac_return=已启用
- #
- echo "-----------------------------------------------"
- echo -e "\033[30;47m欢迎使用功能设置菜单:\033[0m"
- echo "-----------------------------------------------"
- echo -e " 1 切换防火墙运行模式: \033[36m$redir_mod\033[0m"
- [ "$disoverride" != "1" ] && {
- echo -e " 2 切换DNS运行模式: \033[36m$dns_mod\033[0m"
- echo -e " 3 跳过本地证书验证: \033[36m$skip_cert\033[0m ————解决节点证书验证错误"
- }
- echo -e " 4 只代理常用端口: \033[36m$common_ports\033[0m ————用于过滤P2P流量"
- echo -e " 5 过滤局域网设备: \033[36m$mac_return\033[0m ————使用黑/白名单进行过滤"
- echo -e " 7 屏蔽QUIC流量: \033[36m$quic_rj\033[0m ————优化视频性能"
- [ "$disoverride" != "1" ] && {
- [ "$dns_mod" != "fake-ip" ] &&
- echo -e " 8 CN_IP绕过内核: \033[36m$cn_ip_route\033[0m ————优化性能,不兼容Fake-ip"
- [ "$dns_mod" != "redir_host" ] &&
- echo -e " 9 管理Fake-ip过滤列表"
- }
- echo "-----------------------------------------------"
- echo -e " 0 返回上级菜单 \033[0m"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0)
- i=
- ;;
- 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
- normal_set
- ;;
- 2)
- set_dns_mod
- sleep 1
- normal_set
- ;;
- 3)
- echo "-----------------------------------------------"
- if [ "$skip_cert" = "未开启" ] >/dev/null 2>&1; then
- echo -e "\033[33m已设为开启跳过本地证书验证!!\033[0m"
- skip_cert=已开启
- else
- echo -e "\033[33m已设为禁止跳过本地证书验证!!\033[0m"
- skip_cert=未开启
- fi
- setconfig skip_cert $skip_cert
- normal_set
- ;;
- 4)
- set_common_ports() {
- if [ "$common_ports" = "未开启" ]; then
- echo -e "\033[33m当前代理端口为:【$multiport】\033[0m"
- echo -e "\033[31m注意,fake-ip模式下,非常用端口的域名连接将不受影响!!\033[0m"
- read -p "是否修改默认端口?(1/0) > " res
- [ "$res" = "1" ] && {
- read -p "请输入自定义端口,注意用小写逗号分隔 > " text
- [ -n "$text" ] && setconfig multiport $text && echo -e "\033[33m已设为代理【$multiport】端口!!\033[0m"
- }
- common_ports=已开启
- sleep 1
- else
- echo -e "\033[33m已设为代理全部端口!!\033[0m"
- common_ports=未开启
- fi
- setconfig common_ports $common_ports
- }
- echo "-----------------------------------------------"
- if [ -n "$(pidof CrashCore)" ]; then
- read -p "切换时将停止服务,是否继续?(1/0) > " res
- [ "$res" = 1 ] && ${CRASHDIR}/start.sh stop && set_common_ports
- else
- set_common_ports
- fi
- normal_set
- ;;
- 5)
- checkcfg_mac=$(cat ${CRASHDIR}/configs/mac)
- macfilter
- if [ -n "$PID" ]; then
- checkcfg_mac_new=$(cat ${CRASHDIR}/configs/mac)
- [ "$checkcfg_mac" != "$checkcfg_mac_new" ] && checkrestart
- fi
- normal_set
- ;;
- 7)
- echo "-----------------------------------------------"
- if [ -n "$(echo "$redir_mod" | grep -oE '混合|Tproxy|Tun')" ]; then
- if [ "$quic_rj" = "未开启" ]; then
- echo -e "\033[33m已禁止QUIC流量通过ShellCrash内核!!\033[0m"
- quic_rj=已启用
- else
- echo -e "\033[33m已取消禁止QUIC协议流量!!\033[0m"
- quic_rj=未开启
- fi
- setconfig quic_rj $quic_rj
- else
- echo -e "\033[33m当前模式默认不会代理UDP流量,无需设置!!\033[0m"
- fi
- sleep 1
- normal_set
- ;;
- 8)
- if [ -n "$(ipset -v 2>/dev/null)" ] || [ "$firewall_mod" = 'nftables' ]; then
- if [ "$cn_ip_route" = "未开启" ]; then
- echo -e "\033[32m已开启CN_IP绕过内核功能!!\033[0m"
- echo -e "\033[31m注意!!!此功能会导致全局模式及一切CN相关规则失效!!!\033[0m"
- cn_ip_route=已开启
- sleep 2
- else
- echo -e "\033[33m已禁用CN_IP绕过内核功能!!\033[0m"
- cn_ip_route=未开启
- fi
- setconfig cn_ip_route $cn_ip_route
- else
- echo -e "\033[31m当前设备缺少ipset模块或未使用nftables模式,无法启用绕过功能!!\033[0m"
- sleep 1
- fi
- normal_set
- ;;
- 9)
- echo "-----------------------------------------------"
- fake_ip_filter
- normal_set
- ;;
- *)
- errornum
- ;;
- esac
-}
-advanced_set() { #进阶设置
- #获取设置默认显示
- [ -z "$proxies_bypass" ] && proxies_bypass=未启用
- [ -z "$start_old" ] && start_old=未开启
- [ -z "$tproxy_mod" ] && tproxy_mod=未开启
- [ -z "$public_support" ] && public_support=未开启
- [ -z "$sniffer" ] && sniffer=未启用
- [ "$crashcore" = "clashpre" ] && [ "$dns_mod" = "redir_host" ] && sniffer=已启用
- [ "$BINDIR" = "/tmp/ShellCrash" ] && mini_clash=已开启 || mini_clash=未开启
- #
- echo "-----------------------------------------------"
- echo -e "\033[30;47m欢迎使用进阶模式菜单:\033[0m"
- echo -e "\033[33m如您并不了解ShellCrash的运行机制,请勿更改本页面功能!\033[0m"
- echo "-----------------------------------------------"
- #echo -e " 2 配置Meta特性"
- echo -e " 3 配置公网及局域网防火墙"
- [ "$disoverride" != "1" ] && {
- echo -e " 4 启用域名嗅探: \033[36m$sniffer\033[0m ————用于流媒体及防DNS污染"
- echo -e " 5 自定义\033[32m端口及秘钥\033[0m"
- }
- echo "-----------------------------------------------"
- echo -e " 9 \033[31m重置/备份/还原\033[0m脚本设置"
- echo -e " 0 返回上级菜单 \033[0m"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- 0) ;;
- 3)
- setfirewall
- advanced_set
- ;;
- 4)
- echo "-----------------------------------------------"
- if [ "$sniffer" = "未启用" ]; 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=已启用
- elif [ "$crashcore" = "clashpre" -a "$dns_mod" = "redir_host" ]; then
- echo -e "\033[31m使用clashpre内核且开启redir-host模式时无法关闭!\033[0m"
- else
- sniffer=未启用
- fi
- setconfig sniffer $sniffer
- echo -e "\033[32m设置成功!\033[0m"
- sleep 1
- advanced_set
- ;;
- 5)
- 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
- advanced_set
- ;;
- 9)
- 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
-}
-#工具脚本
-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_autoSSH_pwd
- mi_autoSSH=已配置
- cp -f /etc/dropbear/dropbear_rsa_host_key ${CRASHDIR}/configs/dropbear_rsa_host_key 2>/dev/null
- cp -f /etc/dropbear/authorized_keys ${CRASHDIR}/configs/authorized_keys 2>/dev/null
- ckcmd nvram && {
- nvram set ssh_en=1
- nvram set telnet_en=1
- nvram set uart_en=1
- nvram set boot_wait=on
- nvram commit
- }
- echo -e "\033[32m设置成功!\033[0m"
- setconfig mi_autoSSH $mi_autoSSH
- setconfig mi_autoSSH_pwd $mi_autoSSH_pwd
- sleep 1
-}
-uninstall() {
- read -p "确认卸载ShellCrash?(警告:该操作不可逆!)[1/0] > " res
- if [ "$res" = '1' ]; then
- #停止服务
- ${CRASHDIR}/start.sh stop 2>/dev/null
- ${CRASHDIR}/start.sh cronset "clash服务" 2>/dev/null
- ${CRASHDIR}/start.sh cronset "订阅链接" 2>/dev/null
- ${CRASHDIR}/start.sh cronset "ShellCrash初始化" 2>/dev/null
- ${CRASHDIR}/start.sh cronset "task.sh" 2>/dev/null
- #移除安装目录
- if [ -n "${CRASHDIR}" ] && [ "${CRASHDIR}" != '/' ]; then
- read -p "是否保留脚本配置及订阅文件?[1/0] > " res
- if [ "$res" = '1' ]; then
- mv -f ${CRASHDIR}/configs /tmp/ShellCrash/configs_bak
- mv -f ${CRASHDIR}/yamls /tmp/ShellCrash/yamls_bak
- mv -f ${CRASHDIR}/jsons /tmp/ShellCrash/jsons_bak
- rm -rf ${CRASHDIR}/*
- mv -f /tmp/ShellCrash/configs_bak "${CRASHDIR}/configs"
- mv -f /tmp/ShellCrash/yamls_bak "${CRASHDIR}/yamls"
- mv -f /tmp/ShellCrash/jsons_bak "${CRASHDIR}/jsons"
- else
- rm -rf ${CRASHDIR}
- fi
- else
- echo -e "\033[31m环境变量配置有误,请尝试手动移除安装目录!\033[0m"
- sleep 1
- fi
- #移除其他内容
- sed -i "/alias $my_alias=*/"d /etc/profile 2>/dev/null
- sed -i '/alias crash=*/'d /etc/profile 2>/dev/null
- sed -i '/export CRASHDIR=*/'d /etc/profile 2>/dev/null
- sed -i '/export crashdir=*/'d /etc/profile 2>/dev/null
- [ -w ~/.zshrc ] && {
- sed -i "/alias $my_alias=*/"d ~/.zshrc
- sed -i '/export CRASHDIR=*/'d ~/.zshrc
- }
- [ -w ~/.bashrc ] && {
- sed -i "/alias $my_alias=*/"d ~/.bashrc
- sed -i '/export CRASHDIR=*/'d ~/.bashrc
- }
- sed -i '/all_proxy/'d $profile
- sed -i '/ALL_PROXY/'d $profile
- sed -i "/启用外网访问SSH服务/d" /etc/firewall.user 2>/dev/null
- sed -i '/ShellCrash初始化/'d /etc/storage/started_script.sh 2>/dev/null
- sed -i '/ShellCrash初始化/'d /jffs/.asusrouter 2>/dev/null
- [ "$BINDIR" != "$CRASHDIR" ] && rm -rf ${BINDIR}
- rm -rf /etc/init.d/shellcrash
- rm -rf /etc/systemd/system/shellcrash.service
- rm -rf /usr/lib/systemd/system/shellcrash.service
- rm -rf /www/clash
- rm -rf /tmp/ShellCrash
- rm -rf /usr/bin/crash
- sed -i '/0:7890/d' /etc/passwd
- userdel -r shellcrash 2>/dev/null
- nvram set script_usbmount="" 2>/dev/null
- nvram commit 2>/dev/null
- uci delete firewall.ShellCrash 2>/dev/null
- uci commit firewall 2>/dev/null
- echo "-----------------------------------------------"
- echo -e "\033[36m已卸载ShellCrash相关文件!有缘再会!\033[0m"
- echo -e "\033[33m请手动关闭当前窗口以重置环境变量!\033[0m"
- echo "-----------------------------------------------"
- exit
- else
- echo -e "\033[31m操作已取消!\033[0m"
- fi
-}
-tools() {
- ssh_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
- }
- [ -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) ;;
- 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
- ssh_tools
- ;;
- 2)
- passwd
- sleep 1
- ssh_tools
- ;;
- 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
- ;;
- *)
- errornum
- ;;
- esac
- }
- #获取设置默认显示
- grep -qE "^\s*[^#].*otapredownload" /etc/crontabs/root >/dev/null 2>&1 && mi_update=禁用 || mi_update=启用
- [ "$mi_autoSSH" = "已配置" ] && mi_autoSSH_type=32m已配置 || mi_autoSSH_type=31m未配置
- [ -f ${CRASHDIR}/tools/tun.ko ] && mi_tunfix=32m已启用 || mi_tunfix=31m未启用
- #
- 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_autoSSH_type \033[0m"
- [ -f /etc/config/ddns ] && echo -e " 7 配置\033[32mDDNS服务\033[0m(需下载相关脚本)"
- [ "$systype" = "mi_snapshot" ] && echo -e " 8 小米设备Tun模块修复 ———— \033[$mi_tunfix \033[0m"
- echo "-----------------------------------------------"
- echo -e " 0 返回上级菜单"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- if [ -z "$num" ]; then
- errornum
- elif [ "$num" = 0 ]; then
- i=
-
- elif [ "$num" = 1 ]; then
- . ${CRASHDIR}/webget.sh && testcommand
-
- elif [ "$num" = 2 ]; then
- . ${CRASHDIR}/webget.sh && userguide
-
- elif [ "$num" = 3 ]; then
- log_pusher
- tools
-
- elif [ "$num" = 4 ]; then
- ssh_tools
- sleep 1
- tools
-
- elif [ "$num" = 7 ]; then
- echo "-----------------------------------------------"
- if [ ! -f ${CRASHDIR}/tools/ShellDDNS.sh ]; then
- echo -e "正在获取在线脚本……"
- ${CRASHDIR}/start.sh 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
- tools
-
- elif [ -x /usr/sbin/otapredownload ] && [ "$num" = 5 ]; 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
- tools
-
- elif [ "$num" = 6 ]; then
- if [ "$systype" = "mi_snapshot" ]; then
- autoSSH
- else
- echo "不支持的设备!"
- fi
- tools
- elif [ "$num" = 8 ]; then
- 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模块补丁文件…………"
- ${CRASHDIR}/start.sh get_bin ${TMPDIR}/tun.ko bin/fix/tun.ko
- if [ "$?" = "0" ]; then
- mv -f ${TMPDIR}/tun.ko ${CRASHDIR}/tools/tun.ko &&
- ${CRASHDIR}/misnap_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
- tools
- else
- errornum
- fi
-}
#主菜单
main_menu() {
#############################
ckstatus
#############################
- echo -e " 1 \033[32m启动/重启\033[0m服务"
- echo -e " 2 内核\033[33m功能设置\033[0m"
- echo -e " 3 \033[31m停止\033[0m内核服务"
- echo -e " 4 内核\033[36m启动设置\033[0m"
- echo -e " 5 配置\033[33m自动任务\033[0m"
- echo -e " 6 导入\033[32m配置文件\033[0m"
- echo -e " 7 内核\033[31m进阶设置\033[0m"
- echo -e " 8 \033[35m其他工具\033[0m"
- echo -e " 9 \033[36m更新/卸载\033[0m"
+ 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
@@ -2243,141 +170,130 @@ main_menu() {
case "$num" in
0)
exit
- ;;
+ ;;
1)
start_service
exit
- ;;
+ ;;
2)
- checkcfg=$(cat $CFG_PATH)
- normal_set
+ checkcfg=$(cat "$CFG_PATH")
+ . "$CRASHDIR"/menus/2_settings.sh && settings
if [ -n "$PID" ]; then
- checkcfg_new=$(cat $CFG_PATH)
+ checkcfg_new=$(cat "$CFG_PATH")
[ "$checkcfg" != "$checkcfg_new" ] && checkrestart
fi
main_menu
- ;;
+ ;;
3)
- ${CRASHDIR}/start.sh stop
+ [ "$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)
- setboot
+ . "$CRASHDIR"/menus/4_setboot.sh && setboot
main_menu
- ;;
+ ;;
5)
- . ${CRASHDIR}/task/task.sh && task_menu
+ . "$CRASHDIR"/menus/5_task.sh && task_menu
main_menu
- ;;
+ ;;
6)
- . ${CRASHDIR}/webget.sh && set_core_config
+ . "$CRASHDIR"/menus/6_core_config.sh && set_core_config
main_menu
- ;;
+ ;;
7)
- checkcfg=$(cat $CFG_PATH)
- advanced_set
+ 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)
+ checkcfg_new=$(cat "$CFG_PATH" "$GT_CFG_PATH")
[ "$checkcfg" != "$checkcfg_new" ] && checkrestart
fi
main_menu
- ;;
+ ;;
8)
- tools
+ . "$CRASHDIR"/menus/8_tools.sh && tools
main_menu
- ;;
+ ;;
9)
- checkcfg=$(cat $CFG_PATH)
- . ${CRASHDIR}/webget.sh && update
+ checkcfg=$(cat "$CFG_PATH")
+ . "$CRASHDIR"/menus/9_upgrade.sh && upgrade
if [ -n "$PID" ]; then
- checkcfg_new=$(cat $CFG_PATH)
+ checkcfg_new=$(cat "$CFG_PATH")
[ "$checkcfg" != "$checkcfg_new" ] && checkrestart
fi
main_menu
- ;;
+ ;;
*)
errornum
exit
- ;;
+ ;;
esac
}
-[ -z "$CRASHDIR" ] && {
- echo "环境变量配置有误!正在初始化~~~"
- CRASHDIR=$(
- cd $(dirname $0)
- pwd
- )
- . ${CRASHDIR}/init.sh
- sleep 1
- echo "请重启SSH窗口以完成初始化!"
- exit
-}
-
-[ -z "$1" ] && main_menu
-
case "$1" in
--h)
- echo -----------------------------------------
- echo "欢迎使用ShellCrash"
- echo -----------------------------------------
- echo " -t 测试模式"
- echo " -h 帮助列表"
- echo " -u 卸载脚本"
- echo " -i 初始化脚本"
- echo " -d 测试运行"
- echo -----------------------------------------
- echo " crash -s start 启动服务"
- echo " crash -s stop 停止服务"
- echo " 安装目录/start.sh init 开机初始化"
- echo -----------------------------------------
- echo "在线求助:t.me/ShellClash"
- echo "官方博客:juewuy.github.io"
- echo "发布页面:github.com/juewuy/ShellCrash"
- echo -----------------------------------------
+ "")
+ main_menu
;;
--t)
- shtype=sh && [ -n "$(ls -l /bin/sh | grep -o dash)" ] && shtype=bash
- $shtype -x ${CRASHDIR}/menu.sh
+ -t)
+ shtype=sh && [ -n "$(ls -l /bin/sh | grep -o dash)" ] && shtype=bash
+ $shtype -x "$CRASHDIR"/menu.sh
;;
--s)
- ${CRASHDIR}/start.sh $2 $3 $4 $5 $6
+ -s)
+ "$CRASHDIR"/start.sh $2 $3 $4 $5 $6
;;
--i)
- . ${CRASHDIR}/init.sh
+ -i)
+ . "$CRASHDIR"/init.sh 2>/dev/null
;;
--st)
- shtype=sh && [ -n "$(ls -l /bin/sh | grep -o dash)" ] && shtype=bash
- $shtype -x ${CRASHDIR}/start.sh $2 $3 $4 $5 $6
+ -st)
+ shtype=sh && [ -n "$(ls -l /bin/sh | grep -o dash)" ] && shtype=bash
+ $shtype -x "$CRASHDIR"/start.sh $2 $3 $4 $5 $6
;;
--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
+ -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
;;
--u)
- uninstall
+ -u)
+ . "$CRASHDIR"/menus/uninstall.sh && uninstall
;;
-*)
- $0 -h
+ *)
+ 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 -----------------------------------------
;;
esac
diff --git a/scripts/menus/1_start.sh b/scripts/menus/1_start.sh
new file mode 100644
index 00000000..29b13ca3
--- /dev/null
+++ b/scripts/menus/1_start.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+[ -n "$__IS_MODULE_1_START_LOADED" ] && return
+__IS_MODULE_1_START_LOADED=1
+
+#启动相关
+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}"
+ fi
+ return 0
+}
+start_core() {
+ if echo "$crashcore" | grep -q 'singbox'; then
+ core_config="$CRASHDIR"/jsons/config.json
+ else
+ core_config="$CRASHDIR"/yamls/config.yaml
+ fi
+ 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
+ }
+ else
+ echo -e "\033[31m没有找到${crashcore}配置文件,请先导入配置文件!\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"
+ else
+ start_core
+ fi
+}
diff --git a/scripts/menus/2_settings.sh b/scripts/menus/2_settings.sh
new file mode 100644
index 00000000..3c880c2a
--- /dev/null
+++ b/scripts/menus/2_settings.sh
@@ -0,0 +1,931 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+[ -n "$__IS_MODULE_2_SETTINGS_LOADED" ] && return
+__IS_MODULE_2_SETTINGS_LOADED=1
+
+settings() { #功能设置
+ #获取设置默认显示
+ [ -z "$skip_cert" ] && skip_cert=ON
+ [ -z "$sniffer" ] && sniffer=OFF
+ [ -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
+}
+
+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(6)列表: \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"
+ echo "-----------------------------------------------"
+ echo -e "当前默认透明路由的网段为: \033[32m$(ip a 2>&1 | grep -w 'inet' | grep 'global' | grep 'br' | grep -v 'iot' | grep -E ' 1(92|0|72)\.' | sed 's/.*inet.//g' | sed 's/br.*$//g' | sed 's/metric.*$//g' | tr '\n' ' ' && echo) \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$fw_filter_lan_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已切换为$fw_filter_lan_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"
+ else
+ echo -e "\033[31m输入有误,请重新输入!\033[0m"
+ 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"
+ 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
+}
+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
+ 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 ;;
+ 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
+ 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
+}
diff --git a/scripts/menus/4_setboot.sh b/scripts/menus/4_setboot.sh
new file mode 100644
index 00000000..d20f70e0
--- /dev/null
+++ b/scripts/menus/4_setboot.sh
@@ -0,0 +1,184 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+[ -n "$__IS_MODULE_4_SETBOOT_LOADED" ] && return
+__IS_MODULE_4_SETBOOT_LOADED=1
+
+allow_autostart() {
+ [ -f /etc/rc.common -a "$(cat /proc/1/comm)" = "procd" ] && /etc/init.d/shellcrash enable
+ ckcmd systemctl && systemctl enable shellcrash.service >/dev/null 2>&1
+ grep -q 's6' /proc/1/comm && touch /etc/s6-overlay/s6-rc.d/user/contents.d/afstart
+ rc-status -r >/dev/null 2>&1 && rc-update add shellcrash default >/dev/null 2>&1
+ rm -rf "$CRASHDIR"/.dis_startup
+}
+
+disable_autostart() {
+ [ -d /etc/rc.d ] && cd /etc/rc.d && rm -rf *shellcrash >/dev/null 2>&1 && cd - >/dev/null
+ ckcmd systemctl && systemctl disable shellcrash.service >/dev/null 2>&1
+ grep -q 's6' /proc/1/comm && rm -rf /etc/s6-overlay/s6-rc.d/user/contents.d/afstart
+ rc-status -r >/dev/null 2>&1 && rc-update del shellcrash default >/dev/null 2>&1
+ touch "$CRASHDIR"/.dis_startup
+}
+
+# 启动设置菜单
+setboot() {
+ while true; do
+ [ -z "$start_old" ] && start_old=OFF
+ [ -z "$start_delay" -o "$start_delay" = 0 ] && delay=未设置 || delay="${start_delay}秒"
+ check_autostart && auto_set="\033[33m禁止" || auto_set="\033[32m允许"
+ [ "${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 "-----------------------------------------------"
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ if check_autostart; then
+ # 禁止自启动:删除各系统的启动项
+ disable_autostart
+ echo -e "\033[33m已禁止ShellCrash开机启动!\033[0m"
+ else
+ # 允许自启动:配置各系统的启动项
+ allow_autostart
+ echo -e "\033[32m已设置ShellCrash开机启动!\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
+ 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初始化"
+ start_old=OFF
+ setconfig start_old "$start_old"
+ "$CRASHDIR"/start.sh stop
+
+ else
+ echo -e "\033[31m当前设备不支持以其他模式启动!!\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
+ 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"
+ ;;
+ *)
+ echo -e "\033[31m输入有误,或超过300秒,请重新输入!\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"
+ else
+ [ "$BINDIR" = "$CRASHDIR" ] && BINDIR="$TMPDIR"
+ echo -e "\033[32m已经启用小闪存功能!\033[0m"
+ echo -e "如需更换目录,请使用【设置小闪存目录】功能\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"
+ else
+ rm -rf /tmp/ShellCrash
+ BINDIR="$CRASHDIR"
+ echo -e "\033[33m已经停用小闪存功能!\033[0m"
+ fi
+ fi
+ setconfig 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
+ fi
+ }
+ set_usb_dir
+ ;;
+ 3)
+ input_dir() {
+ read -p "请输入自定义目录 > " BINDIR
+ if [ ! -d "$BINDIR" ]; then
+ echo "\033[31m输入错误!请重新设置!\033[0m"
+ input_dir
+ fi
+ }
+ input_dir
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+ setconfig BINDIR "$BINDIR" "$CRASHDIR"/configs/command.env
+ ;;
+ 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' ] && {
+ if [ "$network_check" = "OFF" ]; then
+ network_check=ON
+ else
+ network_check=OFF
+ fi
+ setconfig network_check "$network_check"
+ }
+ sleep 1
+ ;;
+ *)
+ errornum
+ sleep 1
+ break
+ ;;
+ esac
+ done
+}
diff --git a/scripts/task.sh b/scripts/menus/5_task.sh
similarity index 53%
rename from scripts/task.sh
rename to scripts/menus/5_task.sh
index dbcfdb86..abe5784b 100644
--- a/scripts/task.sh
+++ b/scripts/menus/5_task.sh
@@ -1,196 +1,13 @@
#!/bin/sh
# Copyright (C) Juewuy
-#加载全局变量
-[ -z "$CRASHDIR" ] && CRASHDIR=$(cd "$(dirname "$(dirname "$0")")"; pwd)
-[ -z "$BINDIR" ] && BINDIR=${CRASHDIR}
-CFG_PATH=${CRASHDIR}/configs/ShellCrash.cfg
-TMPDIR=/tmp/ShellCrash && [ ! -f ${TMPDIR} ] && mkdir -p ${TMPDIR}
-. $CFG_PATH >/dev/null 2>&1
-[ -n "$(tar --help 2>&1|grep -o 'no-same-owner')" ] && tar_para='--no-same-owner' #tar命令兼容
+[ -n "$__IS_MODULE_5_TASK_LOADED" ] && return
+__IS_MODULE_5_TASK_LOADED=1
-setconfig(){
- #参数1代表变量名,参数2代表变量值,参数3即文件路径
- [ -z "$3" ] && configpath=$CFG_PATH || configpath=$3
- [ -n "$(grep "\b${1}=" $configpath)" ] && sed -i "s#\b${1}=.*#${1}=${2}#g" $configpath || echo "${1}=${2}" >> $configpath
-}
-ckcmd(){ #检查命令是否存在
- command -v sh >/dev/null 2>&1 && command -v $1 >/dev/null 2>&1 || type $1 >/dev/null 2>&1
-}
-
-#任务命令
-check_update(){ #检查更新工具
- ${CRASHDIR}/start.sh 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
- logger "任务【自动更新内核】中止-未检测到版本更新"
- exit 1
- else
- echo "$crashcore" | grep -q 'singbox' && core_new=singbox || core_new=clash
- if [ -n "$custcorelink" ];then
- zip_type=$(echo $custcorelink | grep -oE 'tar.gz$')
- [ -z "$zip_type" ] && zip_type=$(echo $custcorelink | grep -oE 'gz$')
- if [ -n "$zip_type" ];then
- ${CRASHDIR}/start.sh webget ${TMPDIR}/core_new.${zip_type} ${custcorelink}
- fi
- else
- ${CRASHDIR}/start.sh get_bin ${TMPDIR}/core_new.tar.gz bin/${crashcore}/${core_new}-linux-${cpucore}.tar.gz
- fi
- if [ "$?" != "0" ];then
- logger "任务【自动更新内核】出错-下载失败!"
- ${TMPDIR}/CrashCore.tar.gz
- return 1
- else
- [ -n "$(pidof CrashCore)" ] && ${CRASHDIR}/start.sh stop #停止内核服务防止内存不足
- [ -f ${TMPDIR}/core_new.tar.gz ] && {
- mkdir -p ${TMPDIR}/core_new_dir
- [ "$BINDIR" = "$TMPDIR" ] && rm -rf ${TMPDIR}/CrashCore #小闪存模式防止空间不足
- tar -zxf "${TMPDIR}/core_new.tar.gz" ${tar_para} -C ${TMPDIR}/core_new_dir/
- for file in $(find ${TMPDIR}/core_new_dir 2>/dev/null);do
- [ -f $file ] && [ -n "$(echo $file | sed 's#.*/##' | grep -iE '(CrashCore|sing|meta|mihomo|clash|premium)')" ] && mv -f $file ${TMPDIR}/core_new
- done
- rm -rf ${TMPDIR}/core_new_dir
- }
- [ -f ${TMPDIR}/core_new.gz ] && gunzip ${TMPDIR}/core_new.gz >/dev/null && rm -rf ${TMPDIR}/core_new.gz
- chmod +x ${TMPDIR}/core_new
- [ "$crashcore" = unknow ] && setcoretype
- if echo "$crashcore" | grep -q 'singbox';then
- core_v=$(${TMPDIR}/core_new version 2>/dev/null | grep version | awk '{print $3}')
- else
- core_v=$(${TMPDIR}/core_new -v 2>/dev/null | head -n 1 | sed 's/ linux.*//;s/.* //')
- fi
- if [ -z "$core_v" ];then
- logger "任务【自动更新内核】出错-内核校验失败!"
- rm -rf ${TMPDIR}/core_new.tar.gz
- rm -rf ${TMPDIR}/core_new
- ${CRASHDIR}/start.sh start
- return 1
- else
- mv -f ${TMPDIR}/core_new ${TMPDIR}/CrashCore
- if [ -f ${TMPDIR}/core_new.tar.gz ];then
- mv -f ${TMPDIR}/core_new.tar.gz ${BINDIR}/CrashCore.tar.gz
- else
- tar -zcf ${BINDIR}/CrashCore.tar.gz ${tar_para} -C ${TMPDIR} CrashCore
- fi
- logger "任务【自动更新内核】下载完成,正在重启服务!"
- setconfig core_v $core_v
- ${CRASHDIR}/start.sh start
- return 0
- fi
- fi
- fi
-}
-update_scripts(){ #自动更新脚本
- #检查版本
- check_update version
- if [ -z "$versionsh" -o "$versionsh" = "versionsh_l" ];then
- logger "任务【自动更新脚本】中止-未检测到版本更新"
- exit 1
- else
- ${CRASHDIR}/start.sh get_bin ${TMPDIR}/clashfm.tar.gz "bin/update.tar.gz"
- if [ "$?" != "0" ];then
- rm -rf ${TMPDIR}/clashfm.tar.gz
- logger "任务【自动更新内核】出错-下载失败!"
- return 1
- else
- #停止服务
- ${CRASHDIR}/start.sh stop
- #解压
- tar -zxf "${TMPDIR}/clashfm.tar.gz" ${tar_para} -C ${CRASHDIR}/
- if [ $? -ne 0 ];then
- rm -rf ${TMPDIR}/clashfm.tar.gz
- logger "任务【自动更新内核】出错-解压失败!"
- ${CRASHDIR}/start.sh start
- return 1
- else
- . ${CRASHDIR}/init.sh >/dev/null
- ${CRASHDIR}/start.sh start
- return 0
- fi
- fi
- fi
-}
-update_mmdb(){ #自动更新数据库
- getgeo(){
- #检查版本
- check_update bin/version
- geo_v="$(echo $2 | awk -F "." '{print $1}')_v" #获取版本号类型比如Country_v
- geo_v_new=$GeoIP_v
- geo_v_now=$(eval echo \$$geo_v)
- if [ -z "$geo_v_new" -o "$geo_v_new" = "$geo_v_now" ];then
- logger "任务【自动更新数据库文件】跳过-未检测到$2版本更新"
- else
- #更新文件
- ${CRASHDIR}/start.sh get_bin ${TMPDIR}/$1 "bin/geodata/$2"
- if [ "$?" != "0" ];then
- logger "任务【自动更新数据库文件】更新【$2】下载失败!"
- rm -rf ${TMPDIR}/$1
- else
- mv -f ${TMPDIR}/$1 ${BINDIR}/$1
- setconfig $geo_v $GeoIP_v
- 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
- [ -n "${mrs_geosite_cn_v}" -a -s $CRASHDIR/geosite-cn.mrs ] && getgeo geosite-cn.mrs mrs_geosite_cn.mrs
- [ -n "${srs_geoip_cn_v}" -a -s $CRASHDIR/geoip-cn.srs ] && getgeo geoip-cn.srs srs_geoip_cn.srs
- [ -n "${srs_geosite_cn_v}" -a -s $CRASHDIR/geosite-cn.srs ] && getgeo geosite-cn.srs srs_geosite_cn.srs
- return 0
-}
-reset_firewall(){ #重设透明路由防火墙
- ${CRASHDIR}/start.sh stop_firewall
- ${CRASHDIR}/start.sh afstart
-}
-ntp(){
- [ "$crashcore" != singbox ] && ckcmd ntpd && ntpd -n -q -p 203.107.6.88 >/dev/null 2>&1 || exit 0 &
-}
+#通用工具
+. "$CRASHDIR"/libs/set_config.sh
+. "$CRASHDIR"/libs/set_cron.sh
#任务工具
-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
- ${CRASHDIR}/start.sh logger "$1" 0 "$push"
-}
-croncmd(){
- if [ -n "$(crontab -h 2>&1 | grep '\-l')" ];then
- crontab $1
- else
- crondir="$(crond -h 2>&1 | grep -oE 'Default:.*' | awk -F ":" '{print $2}')"
- [ ! -w "$crondir" ] && crondir="/etc/storage/cron/crontabs"
- [ ! -w "$crondir" ] && crondir="/var/spool/cron/crontabs"
- [ ! -w "$crondir" ] && crondir="/var/spool/cron"
- if [ -w "$crondir" ];then
- [ "$1" = "-l" ] && cat $crondir/$USER 2>/dev/null
- [ -f "$1" ] && cat $1 > $crondir/$USER
- else
- echo "你的设备不支持定时任务配置,脚本大量功能无法启用,请尝试使用搜索引擎查找安装方式!"
- fi
- fi
-}
-cronset(){
- # 参数1代表要移除的关键字,参数2代表要添加的任务语句
- tmpcron=${TMPDIR}/cron_$USER
- croncmd -l > $tmpcron 2>/dev/null
- sed -i "/$1/d" $tmpcron
- sed -i '/^$/d' $tmpcron
- echo "$2" >> $tmpcron
- croncmd $tmpcron
- #华硕/Padavan固件存档在本地,其他则删除
- [ -d /jffs -o -d /etc/storage/clash -o -d /etc/storage/ShellCrash ] && mv -f $tmpcron ${CRASHDIR}/task/cron || rm -f $tmpcron
-}
set_cron(){
[ -z $week ] && week=*
[ -z $hour ] && hour=*
@@ -208,7 +25,7 @@ set_cron(){
}
set_service(){
# 参数1代表要任务类型,参数2代表任务ID,参数3代表任务描述,参数4代表running任务cron时间
- task_file=${CRASHDIR}/task/$1
+ task_file="$CRASHDIR"/task/$1
[ -s $task_file ] && sed -i "/$3/d" $task_file
#运行时每分钟执行的任务特殊处理
if [ "$1" = "running" ];then
@@ -232,12 +49,12 @@ task_user_add(){ #自定义命令添加
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)
+ 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 "$task_id#$task_command#$task_name" >> "$CRASHDIR"/task/task.user
echo -e "\033[32m自定义任务已添加!\033[0m"
sleep 1
else
@@ -250,13 +67,13 @@ task_user_del(){ #自定义命令删除
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}'
+ 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
+ sed -i "/^$num#/d" "$CRASHDIR"/task/task.user 2>/dev/null
[ "$num" != 0 ] && task_user_del
else
echo -e "\033[31m输入错误,请重新输入!\033[0m"
@@ -268,7 +85,7 @@ task_add(){ #任务添加
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}'
+ 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
@@ -276,9 +93,9 @@ task_add(){ #任务添加
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}')
+ 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
@@ -291,14 +108,15 @@ task_add(){ #任务添加
}
task_del(){ #任务删除
#删除定时任务
- croncmd -l > ${TMPDIR}/cron && sed -i "/$1/d" ${TMPDIR}/cron && croncmd ${TMPDIR}/cron
- rm -f ${TMPDIR}/cron
+ croncmd -l > "$TMPDIR"/cron
+ sed -i "/$1/d" "$TMPDIR"/cron && croncmd "$TMPDIR"/cron
+ rm -f "$TMPDIR"/cron
#删除条件任务
- sed -i "/$1/d" ${CRASHDIR}/task/cron 2>/dev/null
- sed -i "/$1/d" ${CRASHDIR}/task/bfstart 2>/dev/null
- sed -i "/$1/d" ${CRASHDIR}/task/afstart 2>/dev/null
- sed -i "/$1/d" ${CRASHDIR}/task/running 2>/dev/null
- sed -i "/$1/d" ${CRASHDIR}/task/affirewall 2>/dev/null
+ 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 "-----------------------------------------------"
@@ -308,6 +126,9 @@ task_type(){ #任务条件选择菜单
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"
@@ -393,20 +214,20 @@ task_type(){ #任务条件选择菜单
task_manager(){ #任务管理列表
echo "-----------------------------------------------"
#抽取并生成临时列表
- croncmd -l > ${TMPDIR}/task_cronlist
- cat ${TMPDIR}/task_cronlist ${CRASHDIR}/task/running 2>/dev/null | sort -u | grep -oE "task/task.sh .*" | awk -F ' ' '{print $2" "$3}' > ${TMPDIR}/task_list
- cat ${CRASHDIR}/task/bfstart ${CRASHDIR}/task/afstart ${CRASHDIR}/task/affirewall 2>/dev/null | awk -F ' ' '{print $2" "$3}' >> ${TMPDIR}/task_list
- cat ${TMPDIR}/task_cronlist 2>/dev/null | sort -u | grep -oE " #.*" | grep -v "守护" | awk -F '#' '{print "0 旧版任务-"$2}' >> ${TMPDIR}/task_list
- sed -i '/^ *$/d' ${TMPDIR}/task_list
- rm -rf ${TMPDIR}/task_cronlist
+ croncmd -l > "$TMPDIR"/task_cronlist
+ cat "$TMPDIR"/task_cronlist "$CRASHDIR"/task/running 2>/dev/null | sort -u | grep -oE "task/task.sh .*" | awk -F ' ' '{print $2" "$3}' > "$TMPDIR"/task_list
+ cat "$CRASHDIR"/task/bfstart "$CRASHDIR"/task/afstart "$CRASHDIR"/task/affirewall 2>/dev/null | awk -F ' ' '{print $2" "$3}' >> "$TMPDIR"/task_list
+ cat "$TMPDIR"/task_cronlist 2>/dev/null | sort -u | grep -oE " #.*" | grep -v "守护" | awk -F '#' '{print "0 旧版任务-"$2}' >> "$TMPDIR"/task_list
+ sed -i '/^ *$/d' "$TMPDIR"/task_list
+ rm -rf "$TMPDIR"/task_cronlist
#判断为空则返回
- if [ ! -s ${TMPDIR}/task_list ];then
+ 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}'
+ cat "$TMPDIR"/task_list | awk '{print " " NR " " $2}'
echo "-----------------------------------------------"
echo -e " a 清空旧版任务"
echo -e " d 清空任务列表"
@@ -427,7 +248,7 @@ task_manager(){ #任务管理列表
;;
[1-9]|[1-9][0-9])
- task_txt=$(sed -n "$num p" ${TMPDIR}/task_list)
+ 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
@@ -439,7 +260,7 @@ task_manager(){ #任务管理列表
}
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}')
+ 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当前任务"
@@ -459,15 +280,15 @@ task_manager(){ #任务管理列表
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}')
+ 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='执行失败!'
- logger "任务【$task_des】$task_res" 33 off
+ 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"
+ 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
@@ -504,7 +325,7 @@ task_recom(){ #任务推荐
}
task_menu(){ #任务菜单
#检测并创建自定义任务文件
- [ -f ${CRASHDIR}/task/task.user ] || echo '#任务ID(必须>200并顺序排列)#任务命令#任务说明(#号隔开,任务命令和说明中都不允许包含#号)' > ${CRASHDIR}/task/task.user
+ [ -f "$CRASHDIR"/task/task.user ] || echo '#任务ID(必须>200并顺序排列)#任务命令#任务说明(#号隔开,任务命令和说明中都不允许包含#号)' > "$CRASHDIR"/task/task.user
echo "-----------------------------------------------"
echo -e "\033[30;47m欢迎使用自动任务功能:\033[0m"
echo "-----------------------------------------------"
@@ -527,13 +348,13 @@ task_menu(){ #任务菜单
;;
2)
task_manager
- rm -rf ${TMPDIR}/task_list
+ rm -rf "$TMPDIR"/task_list
task_menu
;;
3)
- if [ -n "$(cat ${TMPDIR}/ShellCrash.log | grep '任务【')" ];then
+ if [ -n "$(cat "$TMPDIR"/ShellCrash.log | grep '任务【')" ];then
echo "-----------------------------------------------"
- cat ${TMPDIR}/ShellCrash.log | grep '任务【'
+ cat "$TMPDIR"/ShellCrash.log | grep '任务【'
else
echo -e "\033[31m未找到任务相关执行日志!\033[0m"
fi
@@ -543,7 +364,7 @@ task_menu(){ #任务菜单
4)
echo "-----------------------------------------------"
echo -e "\033[36m请在日志工具中配置相关推送通道及推送开关\033[0m"
- log_pusher
+ . "$CRASHDIR"/menus/8_tools.sh && log_pusher
task_menu
;;
5)
@@ -563,21 +384,4 @@ task_menu(){ #任务菜单
;;
esac
-
}
-
-case "$1" in
- menu)
- task_menu
- ;;
- [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}')
- #logger "任务$task_name 开始执行"
- eval $task_command && task_res=成功 || task_res=失败
- logger "任务【$2】执行$task_res"
- ;;
- *)
- $1
- ;;
-esac
diff --git a/scripts/menus/6_core_config.sh b/scripts/menus/6_core_config.sh
new file mode 100644
index 00000000..c23317c3
--- /dev/null
+++ b/scripts/menus/6_core_config.sh
@@ -0,0 +1,1191 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+[ -n "$__IS_MODULE_6_CORECONFIG_LOADED" ] && return
+__IS_MODULE_6_CORECONFIG_LOADED=1
+
+YAMLSDIR="$CRASHDIR"/yamls
+JSONSDIR="$CRASHDIR"/jsons
+
+#导入订阅、配置文件相关
+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"/libs/core_tools.sh && core_find && "$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" > "$TMPDIR"/providers/outbounds.json
+ rm -rf "$TMPDIR"/provider_temp_file
+ #调用内核测试
+ . "$CRASHDIR"/libs/core_tools.sh && core_find && "$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_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
+}
+
+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
+}
+
+#配置文件主界面
+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
+}
diff --git a/scripts/menus/7_gateway.sh b/scripts/menus/7_gateway.sh
new file mode 100644
index 00000000..de3d7c5c
--- /dev/null
+++ b/scripts/menus/7_gateway.sh
@@ -0,0 +1,606 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+[ -n "$__IS_MODULE_7_GATEWAY_LOADED" ] && return
+__IS_MODULE_7_GATEWAY_LOADED=1
+
+. "$GT_CFG_PATH"
+. "$CRASHDIR"/menus/check_port.sh
+. "$CRASHDIR"/libs/gen_base64.sh
+
+#访问与控制主菜单
+gateway(){
+ 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
+}
+#公网防火墙
+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$dns_port,$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
+}
+#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
+ ;;
+ *)
+ errornum
+ ;;
+ esac
+}
+#自定义入站
+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 &&
+ 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
+}
+
diff --git a/scripts/menus/8_tools.sh b/scripts/menus/8_tools.sh
new file mode 100644
index 00000000..25704d0f
--- /dev/null
+++ b/scripts/menus/8_tools.sh
@@ -0,0 +1,808 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+[ -n "$__IS_MODULE_8_TOOLS_LOADED" ] && return
+__IS_MODULE_8_TOOLS_LOADED=1
+
+. "$CRASHDIR"/libs/logger.sh
+. "$CRASHDIR"/libs/web_get_bin.sh
+
+stop_iptables() {
+ iptables -w -t nat -D PREROUTING -p tcp -m multiport --dports $ssh_port -j REDIRECT --to-ports 22 >/dev/null 2>&1
+ ip6tables -w -t nat -A PREROUTING -p tcp -m multiport --dports $ssh_port -j REDIRECT --to-ports 22 >/dev/null 2>&1
+}
+
+ssh_tools() {
+ while true; do
+ [ -n "$(cat /etc/firewall.user 2>&1 | grep '启用外网访问SSH服务')" ] && ssh_ol=禁止 || ssh_ol=开启
+ [ -z "$ssh_port" ] && ssh_port=10022
+ 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
+}
+
+#工具与优化
+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
+}
+
+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=已配置
+ cp -f /etc/dropbear/dropbear_rsa_host_key "$CRASHDIR"/configs/dropbear_rsa_host_key 2>/dev/null
+ cp -f /etc/dropbear/authorized_keys "$CRASHDIR"/configs/authorized_keys 2>/dev/null
+ ckcmd nvram && {
+ nvram set ssh_en=1
+ nvram set telnet_en=1
+ nvram set uart_en=1
+ nvram set boot_wait=on
+ nvram commit
+ }
+ echo -e "\033[32m设置成功!\033[0m"
+ setconfig mi_mi_autoSSH $mi_mi_autoSSH
+ setconfig mi_mi_autoSSH_pwd $mi_mi_autoSSH_pwd
+ sleep 1
+}
+
+#日志菜单
+log_pusher() {
+ while true; do
+ [ -n "$push_TG" ] && stat_TG=32mON || stat_TG=33mOFF
+ [ -n "$push_Deer" ] && stat_Deer=32mON || stat_Deer=33mOFF
+ [ -n "$push_bark" ] && stat_bark=32mON || stat_bark=33mOFF
+ [ -n "$push_Po" ] && stat_Po=32mON || stat_Po=33mOFF
+ [ -n "$push_PP" ] && stat_PP=32mON || stat_PP=33mOFF
+ [ -n "$push_SynoChat" ] && stat_SynoChat=32mON || stat_SynoChat=33mOFF
+ [ -n "$push_Gotify" ] && stat_Gotify=32mON || stat_Gotify=33mOFF
+ [ "$task_push" = 1 ] && stat_task=32mON || stat_task=33mOFF
+ [ -n "$device_name" ] && device_s=32m$device_name || device_s=33m未设置
+ 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
+}
+
+#测试菜单
+testcommand(){
+ echo "$crashcore" | grep -q 'singbox' && config_path=${JSONSDIR}/config.json || config_path=${YAMLSDIR}/config.yaml
+ 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 "-----------------------------------------------"
+ 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
+}
+
+#新手引导
+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
+ main_menu
+}
diff --git a/scripts/menus/9_upgrade.sh b/scripts/menus/9_upgrade.sh
new file mode 100644
index 00000000..f7b8cca8
--- /dev/null
+++ b/scripts/menus/9_upgrade.sh
@@ -0,0 +1,1082 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+[ -n "$__IS_MODULE_9_UPGRADE_LOADED" ] && return
+__IS_MODULE_9_UPGRADE_LOADED=1
+
+. "$CRASHDIR"/libs/check_dir_avail.sh
+. "$CRASHDIR"/libs/check_cpucore.sh
+. "$CRASHDIR"/libs/web_get_bin.sh
+
+error_down(){
+ echo -e "\033[33m请尝试切换至其他安装源后重新下载!\033[0m"
+ echo -e "或者参考 \033[32;4mhttps://juewuy.github.io/bdaz\033[0m 进行本地安装!"
+ sleep 1
+}
+
+# 更新/卸载功能菜单
+upgrade() {
+ while true; do
+ echo "-----------------------------------------------"
+ [ -z "$version_new" ] && checkupdate
+ [ -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"
+ [ "$(dir_avail "$CRASHDIR")" -le 5120 ] && [ "$CRASHDIR" = "$BINDIR" ] && {
+ echo -e "\033[33m当前目录剩余空间较低,建议开启小闪存模式!\033[0m"
+ sleep 1
+ }
+ 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
+ case "$num" in
+ ""|0)
+ break
+ ;;
+ 1)
+ setscripts
+ ;;
+ 2)
+ setcore
+ ;;
+ 3)
+ setgeo
+ ;;
+ 4)
+ setdb
+ ;;
+ 5)
+ 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
+ ;;
+ 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 "-----------------------------------------------"
+ 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
+}
+
+#更新脚本
+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 -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
+}
+
+#更新内核
+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
+}
+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
+}
+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
+ }
+ }
+}
+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
+}
+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或.gz结尾的压缩文件) > " link
+ [ -n "$link" ] && custcorelink="$link"
+ setcoretype
+ getcore
+ ;;
+ *)
+ ;;
+ 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"
+}
+
+# 内核选择菜单
+setcore() {
+ while true; do
+ # 获取核心及版本信息
+ [ -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/#@#; s#-linux.*$##')"
+ ###
+ 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"
+ [ "$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"
+ }
+ [ "$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"
+ }
+ 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
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ [ -d "/jffs" ] && {
+ echo -e "\033[31mMeta内核使用的GeoSite.dat数据库在华硕设备存在被系统误删的问题,可能无法使用!\033[0m"
+ sleep 3
+ }
+ crashcore=meta
+ custcorelink=''
+ getcore
+ break
+ ;;
+ 2)
+ crashcore=singboxr
+ custcorelink=''
+ getcore
+ break
+ ;;
+ 3)
+ crashcore=singbox
+ custcorelink=''
+ getcore
+ break
+ ;;
+ 4)
+ crashcore=clash
+ custcorelink=''
+ getcore
+ break
+ ;;
+ 5)
+ setziptype
+ ;;
+ 6)
+ setcustcore
+ ;;
+ 7)
+ getcore
+ break
+ ;;
+ 9)
+ setcpucore
+ break
+ ;;
+ *)
+ 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
+}
+
+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
+}
+
+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"
+ 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
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ [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
+ 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
+ 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
+}
+
+#Dashboard
+getdb() {
+ dblink="${update_url}/"
+ echo "-----------------------------------------------"
+ echo "正在连接服务器获取安装文件…………"
+ get_bin "$TMPDIR"/clashdb.tar.gz bin/dashboard/${db_type}.tar.gz
+ if [ "$?" = "1" ]; then
+ echo "-----------------------------------------------"
+ echo -e "\033[31m文件下载失败!\033[0m"
+ echo "-----------------------------------------------"
+ 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
+ #修改默认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
+ elif [ "$db_type" = "meta_xd" ]; then
+ 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
+ fi
+ #写入配置文件
+ setconfig hostdir "'$hostdir'"
+ echo "-----------------------------------------------"
+ echo -e "\033[32m面板安装成功!\033[36m如未生效,请使用【Ctrl+F5】强制刷新浏览器!!!\033[0m"
+ 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 [ "$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"
+ 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
+ case "$num" in
+ "" | 0)
+ return 0
+ ;;
+ 1)
+ dbdir="$CRASHDIR"/ui
+ hostdir=": $db_port/ui"
+ getdb
+ ;;
+ 2)
+ dbdir=/www/clash
+ hostdir='/clash'
+ getdb
+ ;;
+ *)
+ errornum
+ sleep 1
+ return 1
+ ;;
+ esac
+ else
+ dbdir="$CRASHDIR"/ui
+ hostdir=":$db_port/ui"
+ getdb
+ fi
+}
+
+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
+ case "$num" in
+ "" | 0)
+ break
+ ;;
+ 1)
+ db_type=zashboard
+ setconfig external_ui_url "https://github.com/Zephyruso/zashboard/releases/latest/download/dist-cdn-fonts.zip"
+ dbdir
+ ;;
+ 2)
+ db_type=meta_xd
+ setconfig external_ui_url "https://raw.githubusercontent.com/juewuy/ShellCrash/update/bin/dashboard/meta_xd.tar.gz"
+ dbdir
+ ;;
+ 3)
+ db_type=meta_yacd
+ dbdir
+ ;;
+ 4)
+ db_type=clashdb
+ dbdir
+ ;;
+ 5)
+ db_type=meta_db
+ dbdir
+ ;;
+ 6)
+ db_type=yacd
+ 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
+ ;;
+ *)
+ 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
+}
+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
+}
+
+# 写入配置文件
+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"
+}
+
+# 安装源
+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"
+ get_bin "$TMPDIR"/release_version bin/release_version
+ if [ "$?" = "0" ];then
+ echo -e "\033[31m请选择想要回退至的稳定版版本:\033[0m"
+ cat "$TMPDIR"/release_version | awk '{print " "NR" "$1}'
+ echo -e " 0 返回上级菜单"
+ read -p "请输入对应数字 > " num
+ if [ -z "$num" -o "$num" = 0 ]; then
+ continue
+ elif [ $num -le $(cat "$TMPDIR"/release_version 2>/dev/null | awk 'END{print NR}') ]; then
+ release_type=$(cat "$TMPDIR"/release_version | 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"/release_version
+ else
+ echo -e "\033[31m当前源不支持版本回退,请尝试更换其他安装源!\033[0m"
+ sleep 1
+ continue
+ fi
+ ;;
+ *)
+ errornum
+ sleep 1
+ break
+ ;;
+ esac
+ done
+}
diff --git a/scripts/menus/README.md b/scripts/menus/README.md
new file mode 100644
index 00000000..916c5cdd
--- /dev/null
+++ b/scripts/menus/README.md
@@ -0,0 +1,3 @@
+用于存放脚本各级菜单界面的脚本
+
+此处脚本内容包含各类文字说明
\ No newline at end of file
diff --git a/scripts/menus/bot_tg.sh b/scripts/menus/bot_tg.sh
new file mode 100644
index 00000000..05bab2b1
--- /dev/null
+++ b/scripts/menus/bot_tg.sh
@@ -0,0 +1,317 @@
+#!/bin/sh
+
+[ -z "$CRASHDIR" ] && CRASHDIR=$( cd $(dirname $0);cd ..;pwd)
+. "$CRASHDIR"/libs/web_json.sh
+. "$CRASHDIR"/libs/web_get_lite.sh
+. "$CRASHDIR"/menus/running_status.sh
+. "$CRASHDIR"/configs/gateway.cfg
+. "$CRASHDIR"/configs/ShellCrash.cfg
+
+TMPDIR='/tmp/ShellCrash'
+API="https://api.telegram.org/bot$TG_TOKEN"
+STATE_FILE="$TMPDIR/tgbot_state"
+LOGFILE="$TMPDIR/tgbot.log"
+OFFSET=0
+
+### --- 基础函数 --- ###
+web_download(){
+ setproxy
+ if curl --version >/dev/null 2>&1; then
+ curl -kfsSl "$1" -o "$2"
+ else
+ wget -Y on -q --timeout=3 -O "$2" "$1"
+ fi
+}
+web_upload(){
+ curl -ksSfl -X POST --connect-timeout 20 "$API/sendDocument" -F "chat_id=$TG_CHATID" -F "document=@$1" >/dev/null
+}
+send_msg(){
+ TEXT="$1"
+ web_json_post "$API/sendMessage" "{\"chat_id\":\"$TG_CHATID\",\"text\":\"$TEXT\",\"parse_mode\":\"Markdown\"}"
+}
+send_help(){
+ TEXT=$(cat </dev/null 2>&1;then
+ CURL_KB=$(cat < "$LOGFILE"
+}
+do_stop_fw(){
+ redir_mod_bf=$redir_mod
+ redir_mod='纯净模式'
+ setconfig redir_mod $redir_mod
+ "$CRASHDIR"/start.sh stop_firewall
+ echo "ShellCrash 已切换到纯净模式!" > "$LOGFILE"
+}
+do_restart(){
+ "$CRASHDIR"/start.sh restart
+ echo "ShellCrash 服务已重启!" > "$LOGFILE"
+}
+do_set_sub(){
+ #echo "$1" "$2" >> "$CRASHDIR"/configs/providers.cfg
+ echo "错误,还未完成的功能!" > "$LOGFILE"
+
+}
+transport(){ #文件传输
+ case "$CALLBACK" in
+ "ts_get_log")
+ web_upload "$TMPDIR"/ShellCrash.log
+ send_menu
+ ;;
+ "ts_get_bak")
+ now=$(date +%Y%m%d_%H%M%S)
+ FILE="$TMPDIR/configs_$now.tar.gz"
+ tar -zcf "$FILE" -C "$CRASHDIR/configs/" .
+ web_upload "$FILE"
+ rm -rf "$FILE"
+ send_menu
+ ;;
+ "ts_get_ccf")
+ FILE="$TMPDIR/$config_type.tar.gz"
+ tar -zcf "$FILE" -C "$CRASHDIR/${config_type}s/" .
+ web_upload "$FILE"
+ rm -rf "$FILE"
+ send_menu
+ ;;
+ "ts_up_core")
+ FILE_TYPE=1
+ send_msg "请发送需要上传的内核,必须是以tar.gz,.gz或.upx结尾的【${corename}】内核!"
+ ;;
+ "ts_up_bak")
+ FILE_TYPE=2
+ send_msg "请发送需要还原的备份文件,必须是【.tar.gz】格式!"
+ ;;
+ "ts_up_ccf")
+ FILE_TYPE=3
+ send_msg "请发送需要上传的配置文件,必须是【.${config_type}】格式,支持自定义配置文件"
+ ;;
+ esac
+}
+
+### --- 轮询主进程 --- ###
+polling(){
+ while true; do
+ UPDATES=$(web_get_lite "$API/getUpdates?timeout=25&offset=$OFFSET")
+
+ echo "$UPDATES" | grep -q '"update_id"' || {
+ sleep 10 #防止网络不佳时疯狂请求
+ continue
+ }
+
+ OFFSET=$(echo "$UPDATES" | grep -o '"update_id":[0-9]*' | tail -n1 | cut -d: -f2)
+ OFFSET=$((OFFSET + 1))
+
+ ### --- 处理按钮事件 --- ###
+ 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
+ [ -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
+
+
+ ### --- 处理订阅输入 --- ###
+ TEXT=$(echo "$UPDATES" | grep -o '"text":"[^"]*"' | tail -n1 | sed 's/.*"text":"//;s/"$//')
+
+ if [ "$(cat "$STATE_FILE" 2>/dev/null)" = "await_sub" ]; then
+ echo "" > "$STATE_FILE"
+ do_set_sub "$TEXT"
+ send_msg "订阅更新完成:\n$(cat "$LOGFILE")"
+ send_menu
+ continue
+ fi
+
+
+ ### 处理命令 ###
+ case "$TEXT" in
+ /crash)
+ send_menu
+ ;;
+ /help)
+ send_help
+ ;;
+ esac
+
+ done
+}
+
+#send_menu
+
+polling
+
diff --git a/scripts/menus/bot_tg_bind.sh b/scripts/menus/bot_tg_bind.sh
new file mode 100644
index 00000000..de04cb03
--- /dev/null
+++ b/scripts/menus/bot_tg_bind.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+
+. "$CRASHDIR"/libs/web_get_lite.sh
+
+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"/start.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
+}
+
diff --git a/scripts/menus/bot_tg_service.sh b/scripts/menus/bot_tg_service.sh
new file mode 100644
index 00000000..67a2ee10
--- /dev/null
+++ b/scripts/menus/bot_tg_service.sh
@@ -0,0 +1,19 @@
+
+. "$CRASHDIR"/libs/set_cron.sh
+
+bot_tg_start(){
+ bot_tg_stop
+ . "$CRASHDIR"/starts/start_legacy.sh
+ start_legacy "$CRASHDIR/menus/bot_tg.sh" 'bot_tg'
+ bot_tg_cron
+}
+bot_tg_stop(){
+ cronset 'TG_BOT守护进程'
+ [ -f "$TMPDIR/bot_tg.pid" ] && kill -TERM "$(cat "$TMPDIR/bot_tg.pid")"
+ killall bot_tg.sh 2>/dev/null
+ rm -f "$TMPDIR/bot_tg.pid"
+}
+bot_tg_cron(){
+ cronset 'TG_BOT守护进程'
+ cronset '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
new file mode 100644
index 00000000..1a3c288f
--- /dev/null
+++ b/scripts/menus/check_port.sh
@@ -0,0 +1,17 @@
+#!/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
+}
diff --git a/scripts/menus/ddns.sh b/scripts/menus/ddns.sh
new file mode 100644
index 00000000..933f4bf9
--- /dev/null
+++ b/scripts/menus/ddns.sh
@@ -0,0 +1,178 @@
+#! /bin/bash
+# Copyright (C) Juewuy
+
+
+ddns_menu(){
+ echo -----------------------------------------------
+ echo -e "\033[30;46m欢迎使用DDNS!\033[0m"
+ load_ddns
+}
+add_ddns() {
+ cat >>"$ddns_dir" </dev/null 2>&1 &
+ sleep 3
+ echo 服务已经添加!
+}
+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
+}
+set_ddns_service() {
+ services_dir=/etc/ddns/"$serv"
+ [ -s "$services_dir" ] || services_dir=/usr/share/ddns/list
+ echo -----------------------------------------------
+ echo -e "\033[32m请选择服务提供商\033[0m"
+ cat "$services_dir" | grep -v '^#' | awk '{print " "NR" " $1}'
+ nr=$(cat "$services_dir" | grep -v '^#' | 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 -v '^#' | 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
+}
+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
+}
+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
+}
+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"
+}
+
+
diff --git a/scripts/menus/dns.sh b/scripts/menus/dns.sh
new file mode 100644
index 00000000..ac955054
--- /dev/null
+++ b/scripts/menus/dns.sh
@@ -0,0 +1,229 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+[ -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 [ -n "$(netstat -ntul | grep -E ":$num[[:space:]]")" ];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
+}
+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"
+ else
+ echo -e "你输入的地址是:\033[32m$input\033[0m"
+ read -p "确认添加?(1/0) > " res
+ [ "$res" = 1 ] && echo $input >>${CRASHDIR}/configs/fake_ip_filter
+ fi
+ sleep 1
+ fake_ip_filter
+ ;;
+ esac
+}
+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
+}
diff --git a/scripts/menus/running_status.sh b/scripts/menus/running_status.sh
new file mode 100644
index 00000000..38419d2c
--- /dev/null
+++ b/scripts/menus/running_status.sh
@@ -0,0 +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
+}
diff --git a/scripts/menus/set_crashdir.sh b/scripts/menus/set_crashdir.sh
new file mode 100644
index 00000000..2f1be6c9
--- /dev/null
+++ b/scripts/menus/set_crashdir.sh
@@ -0,0 +1,150 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+. /tmp/SC_tmp/libs/check_dir_avail.sh
+[ -n "$(echo -e | grep e)" ] && echo=echo || echo='echo -e'
+
+set_crashdir() {
+ set_usb_dir() {
+ echo -e "请选择安装目录"
+ du -hL /mnt | awk '{print " "NR" "$2" "$1}'
+ read -p "请输入相应数字 > " num
+ dir=$(du -hL /mnt | awk '{print $2}' | sed -n "$num"p)
+ if [ -z "$dir" ]; then
+ echo -e "\033[31m输入错误!请重新设置!\033[0m"
+ set_usb_dir
+ fi
+ }
+ set_asus_dir() {
+ echo -e "请选择U盘目录"
+ du -hL /tmp/mnt | awk -F/ 'NF<=4' | awk '{print " "NR" "$2" "$1}'
+ read -p "请输入相应数字 > " num
+ dir=$(du -hL /tmp/mnt | awk -F/ 'NF<=4' | awk '{print $2}' | sed -n "$num"p)
+ if [ ! -f "$dir/asusware.arm/etc/init.d/S50downloadmaster" ]; then
+ echo -e "\033[31m未找到下载大师自启文件:$dir/asusware.arm/etc/init.d/S50downloadmaster,请检查设置!\033[0m"
+ set_asus_dir
+ fi
+ }
+ set_cust_dir() {
+ echo "-----------------------------------------------"
+ echo "可用路径 剩余空间:"
+ df -h | awk '{print $6,$4}' | sed 1d
+ echo "路径是必须带 / 的格式,注意写入虚拟内存(/tmp,/opt,/sys...)的文件会在重启后消失!!!"
+ read -p "请输入自定义路径 > " dir
+ if [ "$(dir_avail $dir)" = 0 ] || [ -n "$(echo $dir | grep -E 'tmp|opt|sys')" ]; then
+ echo "\033[31m路径错误!请重新设置!\033[0m"
+ set_cust_dir
+ fi
+ }
+ echo "-----------------------------------------------"
+ if [ -n "$systype" ]; then
+ [ "$systype" = "Padavan" ] && dir=/etc/storage
+ [ "$systype" = "mi_snapshot" ] && {
+ echo -e "\033[33m检测到当前设备为小米官方系统,请选择安装位置\033[0m"
+ [ -d /data ] && $echo " 1 安装到 /data 目录,剩余空间:$(dir_avail /data -h)(支持软固化功能)"
+ [ -d /userdisk ] && $echo " 2 安装到 /userdisk 目录,剩余空间:$(dir_avail /userdisk -h)(支持软固化功能)"
+ [ -d /data/other_vol ] && $echo " 3 安装到 /data/other_vol 目录,剩余空间:$(dir_avail /data/other_vol -h)(支持软固化功能)"
+ $echo " 4 安装到自定义目录(不推荐,不明勿用!)"
+ echo " 0 退出安装"
+ echo "-----------------------------------------------"
+ read -p "请输入相应数字 > " num
+ case "$num" in
+ 1)
+ dir=/data
+ ;;
+ 2)
+ dir=/userdisk
+ ;;
+ 3)
+ dir=/data/other_vol
+ ;;
+ 4)
+ set_cust_dir
+ ;;
+ *)
+ exit 1
+ ;;
+ esac
+ }
+ [ "$systype" = "asusrouter" ] && {
+ echo -e "\033[33m检测到当前设备为华硕固件,请选择安装方式\033[0m"
+ echo -e " 1 基于USB设备安装(限23年9月之前固件,须插入\033[31m任意\033[0mUSB设备)"
+ echo -e " 2 基于自启脚本安装(仅支持梅林及部分非koolshare官改固件)"
+ echo -e " 3 基于U盘+下载大师安装(支持所有固件,限ARM设备,须插入U盘或移动硬盘)"
+ echo -e " 0 退出安装"
+ echo "-----------------------------------------------"
+ read -p "请输入相应数字 > " num
+ case "$num" in
+ 1)
+ read -p "将脚本安装到USB存储/系统闪存?(1/0) > " res
+ [ "$res" = "1" ] && set_usb_dir || dir=/jffs
+ usb_status=1
+ ;;
+ 2)
+ echo -e "如无法正常开机启动,请重新使用USB方式安装!"
+ sleep 2
+ dir=/jffs
+ ;;
+ 3)
+ echo -e "请先在路由器网页后台安装下载大师并启用,之后选择外置存储所在目录!"
+ sleep 2
+ set_asus_dir
+ ;;
+ *)
+ exit 1
+ ;;
+ esac
+ }
+ [ "$systype" = "ng_snapshot" ] && dir=/tmp/mnt
+ else
+ echo -e "\033[33m安装ShellCrash至少需要预留约1MB的磁盘空间\033[0m"
+ echo -e " 1 在\033[32m/etc目录\033[0m下安装(适合root用户)"
+ echo -e " 2 在\033[32m/usr/share目录\033[0m下安装(适合Linux系统)"
+ echo -e " 3 在\033[32m当前用户目录\033[0m下安装(适合非root用户)"
+ echo -e " 4 在\033[32m外置存储\033[0m中安装"
+ echo -e " 5 手动设置安装目录"
+ echo -e " 0 退出安装"
+ echo "-----------------------------------------------"
+ read -p "请输入相应数字 > " num
+ #设置目录
+ case "$num" in
+ 1)
+ dir=/etc
+ ;;
+ 2)
+ dir=/usr/share
+ ;;
+ 3)
+ dir=~/.local/share
+ mkdir -p ~/.config/systemd/user
+ ;;
+ 4)
+ set_usb_dir
+ ;;
+ 5)
+ echo "-----------------------------------------------"
+ echo "可用路径 剩余空间:"
+ df -h | awk '{print $6,$4}' | sed 1d
+ echo "路径是必须带 / 的格式,注意写入虚拟内存(/tmp,/opt,/sys...)的文件会在重启后消失!!!"
+ read -p "请输入自定义路径 > " dir
+ if [ -z "$dir" ]; then
+ echo -e "\033[31m路径错误!请重新设置!\033[0m"
+ setdir
+ fi
+ ;;
+ *)
+ echo "安装已取消"
+ exit 1
+ ;;
+ esac
+ fi
+
+ if [ ! -w $dir ]; then
+ echo -e "\033[31m没有$dir目录写入权限!请重新设置!\033[0m" && sleep 1 && setdir
+ else
+ echo -e "目标目录\033[32m$dir\033[0m空间剩余:$(dir_avail $dir -h)"
+ read -p "确认安装?(1/0) > " res
+ [ "$res" = "1" ] && CRASHDIR=$dir/ShellCrash || setdir
+ fi
+}
+
diff --git a/scripts/menus/task_cmd.sh b/scripts/menus/task_cmd.sh
new file mode 100644
index 00000000..5f3094e1
--- /dev/null
+++ b/scripts/menus/task_cmd.sh
@@ -0,0 +1,146 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+#加载全局变量
+[ -z "$CRASHDIR" ] && CRASHDIR=$( cd $(dirname $0);cd ..;pwd)
+. "$CRASHDIR"/libs/get_config.sh
+#加载工具
+. "$CRASHDIR"/libs/check_cmd.sh
+. "$CRASHDIR"/libs/set_config.sh
+. "$CRASHDIR"/libs/web_get_bin.sh
+. "$CRASHDIR"/libs/logger.sh
+
+task_logger(){
+ [ "$task_push" = 1 ] && push= || push=off
+ [ -n "$2" -a "$2" != 0 ] && echo -e "\033[$2m$1\033[0m"
+ [ "$3" = 'off' ] && push=off
+ echo "$1" |grep -qE '(每隔|时每)([1-9]|[1-9][0-9])分钟' && push=off
+ logger "$1" 0 "$push"
+}
+
+#任务命令
+check_update(){ #检查更新工具
+ get_bin "$TMPDIR"/crashversion "$1" echooff
+ [ "$?" = "0" ] && . "$TMPDIR"/crashversion 2>/dev/null
+ rm -rf "$TMPDIR"/crashversion
+}
+update_core(){ #自动更新内核
+ #检查版本
+ check_update bin/version
+ crash_v_new=$(eval echo \$${crashcore}_v)
+ if [ -z "$crash_v_new" -o "$crash_v_new" = "$core_v" ];then
+ task_logger "任务【自动更新内核】中止-未检测到版本更新"
+ return 0
+ else
+ . "$CRASHDIR"/libs/core_webget.sh && core_webget #调用下载工具
+ case "$?" in
+ 0)
+ task_logger "任务【自动更新内核】下载完成,正在重启服务!"
+ "$CRASHDIR"/start.sh start
+ return 0
+ ;;
+ 1)
+ task_logger "任务【自动更新内核】出错-下载失败!"
+ return 1
+ ;;
+ *)
+ task_logger "任务【自动更新内核】出错-内核校验失败!"
+ "$CRASHDIR"/start.sh start
+ return 1
+ ;;
+ esac
+ fi
+}
+update_scripts(){ #自动更新脚本
+ #检查版本
+ check_update version
+ if [ -z "$versionsh" -o "$versionsh" = "versionsh_l" ];then
+ task_logger "任务【自动更新脚本】中止-未检测到版本更新"
+ return 0
+ else
+ get_bin "$TMPDIR"/clashfm.tar.gz "bin/update.tar.gz"
+ if [ "$?" != "0" ];then
+ rm -rf "$TMPDIR"/clashfm.tar.gz
+ task_logger "任务【自动更新内核】出错-下载失败!"
+ return 1
+ else
+ #停止服务
+ "$CRASHDIR"/start.sh stop
+ #解压
+ tar -zxf "$TMPDIR"/clashfm.tar.gz ${tar_para} -C "$CRASHDIR"/
+ if [ $? -ne 0 ];then
+ rm -rf "$TMPDIR"/clashfm.tar.gz
+ task_logger "任务【自动更新内核】出错-解压失败!"
+ "$CRASHDIR"/start.sh start
+ return 1
+ else
+ . "$CRASHDIR"/init.sh >/dev/null
+ "$CRASHDIR"/start.sh start
+ return 0
+ fi
+ fi
+ fi
+}
+update_mmdb(){ #自动更新数据库
+ getgeo(){
+ #检查版本
+ check_update bin/version
+ geo_v="$(echo $2 | awk -F "." '{print $1}')_v" #获取版本号类型比如Country_v
+ geo_v_new=$GeoIP_v
+ geo_v_now=$(eval echo \$$geo_v)
+ if [ -z "$geo_v_new" -o "$geo_v_new" = "$geo_v_now" ];then
+ task_logger "任务【自动更新数据库文件】跳过-未检测到$2版本更新"
+ else
+ #更新文件
+ get_bin "$TMPDIR"/$1 "bin/geodata/$2"
+ if [ "$?" != "0" ];then
+ task_logger "任务【自动更新数据库文件】更新【$2】下载失败!"
+ rm -rf "$TMPDIR"/$1
+ else
+ mv -f "$TMPDIR"/$1 "$BINDIR"/$1
+ setconfig $geo_v $GeoIP_v
+ task_logger "任务【自动更新数据库文件】更新【$2】成功!"
+ fi
+ fi
+ }
+ [ -n "${cn_mini_v}" -a -s "$CRASHDIR"/Country.mmdb ] && getgeo Country.mmdb cn_mini.mmdb
+ [ -n "${china_ip_list_v}" -a -s "$CRASHDIR"/cn_ip.txt ] && getgeo cn_ip.txt china_ip_list.txt
+ [ -n "${china_ipv6_list_v}" -a -s "$CRASHDIR"/cn_ipv6.txt ] && getgeo cn_ipv6.txt china_ipv6_list.txt
+ [ -n "${geosite_v}" -a -s "$CRASHDIR"/GeoSite.dat ] && getgeo GeoSite.dat geosite.dat
+ [ -n "${geoip_cn_v}" -a -s "$CRASHDIR"/geoip.db ] && getgeo geoip.db geoip_cn.db
+ [ -n "${geosite_cn_v}" -a -s "$CRASHDIR"/geosite.db ] && getgeo geosite.db geosite_cn.db
+ return 0
+}
+reset_firewall(){ #重设透明路由防火墙
+ "$CRASHDIR"/start.sh stop_firewall
+ "$CRASHDIR"/start.sh afstart
+}
+ntp(){
+ [ "$crashcore" != singbox ] && ckcmd ntpd && ntpd -n -q -p 203.107.6.88 >/dev/null 2>&1 || exit 0
+}
+web_save_auto(){
+ . "$CRASHDIR"/libs/web_save.sh && web_save
+}
+update_config() { #更新订阅并重启
+ . "$CRASHDIR"/starts/core_config.sh && get_core_config && "$CRASHDIR"/start.sh start
+}
+hotupdate() { #热更新订阅
+ . "$CRASHDIR"/starts/core_config.sh && get_core_config &&
+ . "$CRASHDIR"/starts/check_core.sh && check_core &&
+ . "$CRASHDIR"/starts/"$target"_modify.sh && modify_"$format" && rm -rf "$TMPDIR"/CrashCore &&
+ . "$CRASHDIR"/libs/web_restore.sh && put_save "http://127.0.0.1:$db_port/configs" "{\"path\":\"$CRASHDIR/config.$format\"}"
+ exit $?
+}
+
+case "$1" in
+ [1-9][0-9][0-9])
+ task_command=$(cat "$CRASHDIR"/task/task.list "$CRASHDIR"/task/task.user 2>/dev/null | grep "$1" | awk -F '#' '{print $2}')
+ task_name=$(cat "$CRASHDIR"/task/task.list "$CRASHDIR"/task/task.user 2>/dev/null | grep "$1" | awk -F '#' '{print $3}')
+ #task_logger "任务$task_name 开始执行"
+ eval $task_command && task_res=成功 || task_res=失败
+ task_logger "任务【$2】执行$task_res"
+ ;;
+ *)
+ "$1"
+ ;;
+esac
diff --git a/scripts/menus/uninstall.sh b/scripts/menus/uninstall.sh
new file mode 100644
index 00000000..4fe3bfda
--- /dev/null
+++ b/scripts/menus/uninstall.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+#卸载
+uninstall() {
+ read -p "确认卸载ShellCrash?(警告:该操作不可逆!)[1/0] > " res
+ if [ "$res" = '1' ]; then
+ #停止服务
+ "$CRASHDIR"/start.sh stop 2>/dev/null
+ "$CRASHDIR"/start.sh cronset "clash服务" 2>/dev/null
+ "$CRASHDIR"/start.sh cronset "订阅链接" 2>/dev/null
+ "$CRASHDIR"/start.sh cronset "ShellCrash初始化" 2>/dev/null
+ "$CRASHDIR"/start.sh cronset "task.sh" 2>/dev/null
+ #移除安装目录
+ if [ -n "$CRASHDIR" ] && [ "$CRASHDIR" != '/' ]; then
+ read -p "是否保留脚本配置及订阅文件?[1/0] > " res
+ if [ "$res" = '1' ]; then
+ mv -f "$CRASHDIR"/configs /tmp/ShellCrash/configs_bak
+ mv -f "$CRASHDIR"/yamls /tmp/ShellCrash/yamls_bak
+ mv -f "$CRASHDIR"/jsons /tmp/ShellCrash/jsons_bak
+ rm -rf "$CRASHDIR"/*
+ mv -f /tmp/ShellCrash/configs_bak "$CRASHDIR"/configs
+ mv -f /tmp/ShellCrash/yamls_bak "$CRASHDIR"/yamls
+ mv -f /tmp/ShellCrash/jsons_bak "$CRASHDIR"/jsons
+ else
+ rm -rf "$CRASHDIR"
+ fi
+ else
+ echo -e "\033[31m环境变量配置有误,请尝试手动移除安装目录!\033[0m"
+ sleep 1
+ fi
+ #移除其他内容
+ sed -i "/alias $my_alias=*/"d /etc/profile 2>/dev/null
+ sed -i '/alias crash=*/'d /etc/profile 2>/dev/null
+ sed -i '/export CRASHDIR=*/'d /etc/profile 2>/dev/null
+ sed -i '/export crashdir=*/'d /etc/profile 2>/dev/null
+ [ -w ~/.zshrc ] && {
+ sed -i "/alias $my_alias=*/"d ~/.zshrc 2>/dev/null
+ sed -i '/export CRASHDIR=*/'d ~/.zshrc 2>/dev/null
+ }
+ sed -i '/all_proxy/'d /etc/profile 2>/dev/null
+ sed -i '/ALL_PROXY/'d /etc/profile 2>/dev/null
+ sed -i "/启用外网访问SSH服务/d" /etc/firewall.user 2>/dev/null
+ sed -i '/ShellCrash初始化/'d /etc/storage/started_script.sh 2>/dev/null
+ sed -i '/ShellCrash初始化/'d /jffs/.asusrouter 2>/dev/null
+ [ "$BINDIR" != "$CRASHDIR" ] && rm -rf "$BINDIR"
+ rm -rf /etc/init.d/shellcrash
+ rm -rf /etc/systemd/system/shellcrash.service
+ rm -rf /usr/lib/systemd/system/shellcrash.service
+ rm -rf /www/clash
+ rm -rf /tmp/ShellCrash
+ rm -rf /usr/bin/crash
+ sed -i '/0:7890/d' /etc/passwd 2>/dev/null
+ userdel -r shellcrash 2>/dev/null
+ nvram set script_usbmount="" 2>/dev/null
+ nvram commit 2>/dev/null
+ echo "-----------------------------------------------"
+ echo -e "\033[36m已卸载ShellCrash相关文件!有缘再会!\033[0m"
+ echo -e "\033[33m请手动关闭当前窗口以重置环境变量!\033[0m"
+ echo "-----------------------------------------------"
+ exit
+ else
+ echo -e "\033[31m操作已取消!\033[0m"
+ fi
+}
diff --git a/scripts/start.sh b/scripts/start.sh
index e7343bc3..e024559c 100644
--- a/scripts/start.sh
+++ b/scripts/start.sh
@@ -2,2046 +2,35 @@
# Copyright (C) Juewuy
#初始化目录
-CRASHDIR=$(
+[ -z "$CRASHDIR" ] && CRASHDIR=$(
cd $(dirname $0)
pwd
)
-#加载执行目录,失败则初始化
-. "$CRASHDIR"/configs/command.env >/dev/null 2>&1
-[ -z "$BINDIR" -o -z "$TMPDIR" -o -z "$COMMAND" ] && . "$CRASHDIR"/init.sh >/dev/null 2>&1
-[ ! -f "$TMPDIR" ] && mkdir -p "$TMPDIR"
-
-#脚本内部工具
-getconfig() { #读取配置及全局变量
- #加载配置文件
- . "$CRASHDIR"/configs/ShellCrash.cfg >/dev/null
- #缺省值
- [ -z "$redir_mod" ] && [ "$USER" = "root" -o "$USER" = "admin" ] && redir_mod='Redir模式'
- [ -z "$redir_mod" ] && firewall_area='4'
- [ -z "$skip_cert" ] && skip_cert=已开启
- [ -z "$dns_mod" ] && dns_mod=fake-ip
- [ -z "$ipv6_redir" ] && ipv6_redir=未开启
- [ -z "$ipv6_dns" ] && ipv6_dns=已开启
- [ -z "$cn_ipv6_route" ] && cn_ipv6_route=未开启
- [ -z "$macfilter_type" ] && macfilter_type=黑名单
- [ -z "$mix_port" ] && mix_port=7890
- [ -z "$redir_port" ] && redir_port=7892
- [ -z "$tproxy_port" ] && tproxy_port=7893
- [ -z "$db_port" ] && db_port=9999
- [ -z "$dns_port" ] && dns_port=1053
- [ -z "$fwmark" ] && fwmark=$redir_port
- routing_mark=$((fwmark + 2))
- [ -z "$table" ] && table=100
- [ -z "$sniffer" ] && sniffer=已开启
- #是否代理常用端口
- [ -z "$common_ports" ] && common_ports=已开启
- [ -z "$multiport" ] && multiport='22,80,143,194,443,465,587,853,993,995,5222,8080,8443'
- [ "$common_ports" = "已开启" ] && ports="-m multiport --dports $multiport"
- #内核配置文件
- if echo "$crashcore" | grep -q 'singbox'; then
- target=singbox
- format=json
- core_config="$CRASHDIR"/jsons/config.json
- else
- target=clash
- format=yaml
- core_config="$CRASHDIR"/yamls/config.yaml
- fi
- #检查$iptable命令可用性
- ckcmd iptables && iptables -h | grep -q '\-w' && iptable='iptables -w' || iptable=iptables
- ckcmd ip6tables && ip6tables -h | grep -q '\-w' && ip6table='ip6tables -w' || ip6table=ip6tables
- #默认dns
- [ -z "$dns_nameserver" ] && dns_nameserver='223.5.5.5, 1.2.4.8'
- [ -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"
- #自动生成ua
- [ -z "$user_agent" -o "$user_agent" = "auto" ] && {
- if echo "$crashcore" | grep -q 'singbox'; then
- user_agent="sing-box/singbox/$core_v"
- elif [ "$crashcore" = meta ]; then
- user_agent="clash.meta/mihomo/$core_v"
- else
- user_agent="clash"
- fi
- }
- [ "$user_agent" = "none" ] && unset user_agent
+. "$CRASHDIR"/libs/get_config.sh
+#加载工具
+. "$CRASHDIR"/libs/set_config.sh
+. "$CRASHDIR"/libs/set_cron.sh
+. "$CRASHDIR"/libs/check_cmd.sh
+. "$CRASHDIR"/libs/compare.sh
+. "$CRASHDIR"/libs/logger.sh
+. "$CRASHDIR"/libs/web_save.sh
+#特殊脚本
+bfstart(){
+ . "$CRASHDIR"/starts/bfstart.sh
}
-setconfig() { #脚本配置工具
- #参数1代表变量名,参数2代表变量值,参数3即文件路径
- [ -z "$3" ] && configpath="$CRASHDIR"/configs/ShellCrash.cfg || configpath="${3}"
- if grep -q "^${1}=" "$configpath"; then
- sed -i "s#^${1}=.*#${1}=${2}#g" "$configpath"
- else
- printf '%s=%s\n' "$1" "$2" >>"$configpath"
- fi
+afstart(){
+ . "$CRASHDIR"/starts/afstart.sh
}
-ckcmd() { #检查命令是否存在
- command -v sh >/dev/null 2>&1 && command -v "$1" >/dev/null 2>&1 || type "$1" >/dev/null 2>&1
+stop_firewall(){
+ . "$CRASHDIR"/starts/fw_stop.sh
}
-ckgeo() { #查找及下载Geo数据文件
- [ ! -d "$BINDIR"/ruleset ] && mkdir -p "$BINDIR"/ruleset
- find --help 2>&1 | grep -q size && find_para=' -size +20' #find命令兼容
- [ -z "$(find "$BINDIR"/"$1" "$find_para" 2>/dev/null)" ] && {
- if [ -n "$(find "$CRASHDIR"/"$1" "$find_para" 2>/dev/null)" ]; then
- mv "$CRASHDIR"/"$1" "$BINDIR"/"$1" #小闪存模式移动文件
- else
- logger "未找到${1}文件,正在下载!" 33
- get_bin "$BINDIR"/"$1" bin/geodata/"$2"
- [ "$?" = "1" ] && rm -rf "${BINDIR}"/"${1}" && logger "${1}文件下载失败,已退出!请前往更新界面尝试手动下载!" 31 && exit 1
- geo_v="$(echo "$2" | awk -F "." '{print $1}')_v"
- setconfig "$geo_v" "$(date +"%Y%m%d")"
- fi
- }
+#保守模式启动
+start_l(){
+ bfstart && {
+ . "$CRASHDIR"/starts/start_legacy.sh
+ start_legacy "$COMMAND" 'shellcrash'
+ } && afstart &
}
-compare() { #对比文件
- if [ ! -f "$1" ] || [ ! -f "$2" ]; then
- return 1
- elif ckcmd cmp; then
- cmp -s "$1" "$2"
- else
- [ "$(cat "$1")" = "$(cat "$2")" ] && return 0 || return 1
- fi
-}
-logger() { #日志工具
- #$1日志内容$2显示颜色$3是否推送
- [ -n "$2" -a "$2" != 0 ] && echo -e "\033[$2m$1\033[0m"
- log_text="$(date "+%G-%m-%d_%H:%M:%S")~$1"
- echo "$log_text" >>"$TMPDIR"/ShellCrash.log
- [ "$(wc -l "$TMPDIR"/ShellCrash.log | awk '{print $1}')" -gt 99 ] && sed -i '1,50d' "$TMPDIR"/ShellCrash.log
- #推送工具
- webpush() {
- [ -n "$(pidof CrashCore)" ] && {
- [ -n "$authentication" ] && auth="$authentication@"
- export https_proxy="http://${auth}127.0.0.1:$mix_port"
- }
- if curl --version >/dev/null 2>&1; then
- curl -kfsSl -X POST --connect-timeout 3 -H "Content-Type: application/json; charset=utf-8" "$1" -d "$2" >/dev/null 2>&1
- elif wget --version >/dev/null 2>&1; then
- wget -Y on -q --timeout=3 -O - --method=POST --header="Content-Type: application/json; charset=utf-8" --body-data="$2" "$1" >/dev/null 2>&1
- else
- echo "找不到有效的curl或wget应用,请先安装!"
- fi
- }
- [ -z "$3" ] && {
- [ -n "$device_name" ] && log_text="$log_text($device_name)"
- [ -n "$push_TG" ] && {
- url="https://api.telegram.org/bot${push_TG}/sendMessage"
- [ "$push_TG" = 'publictoken' ] && url='https://tgbot.jwsc.eu.org/publictoken/sendMessage'
- content="{\"chat_id\":\"${chat_ID}\",\"text\":\"$log_text\"}"
- webpush "$url" "$content" &
- }
- [ -n "$push_bark" ] && {
- url="${push_bark}"
- content="{\"body\":\"${log_text}\",\"title\":\"ShellCrash日志推送\",\"level\":\"passive\",\"badge\":\"1\"}"
- webpush "$url" "$content" &
- }
- [ -n "$push_Deer" ] && {
- url="https://api2.pushdeer.com/message/push"
- content="{\"pushkey\":\"${push_Deer}\",\"text\":\"$log_text\"}"
- webpush "$url" "$content" &
- }
- [ -n "$push_Po" ] && {
- url="https://api.pushover.net/1/messages.json"
- content="{\"token\":\"${push_Po}\",\"user\":\"${push_Po_key}\",\"title\":\"ShellCrash日志推送\",\"message\":\"$log_text\"}"
- webpush "$url" "$content" &
- }
- [ -n "$push_PP" ] && {
- url="http://www.pushplus.plus/send"
- content="{\"token\":\"${push_PP}\",\"title\":\"ShellCrash日志推送\",\"content\":\"$log_text\"}"
- webpush "$url" "$content" &
- }
- # 新增Gotify推送
- [ -n "$push_Gotify" ] && {
- url="${push_Gotify}"
- content="{\"title\":\"ShellCrash日志推送\",\"message\":\"$log_text\",\"priority\":5}"
- webpush "$url" "$content" &
- }
- [ -n "$push_SynoChat" ] && {
- url="${push_ChatURL}/webapi/entry.cgi?api=SYNO.Chat.External&method=chatbot&version=2&token=${push_ChatTOKEN}"
- content="payload={\"text\":\"${log_text}\", \"user_ids\":[${push_ChatUSERID}]}"
- webpush "$url" "$content" &
- #curl -X POST "${push_ChatURL}/webapi/entry.cgi?api=SYNO.Chat.External&method=chatbot&version=2&token=${push_ChatTOKEN}" -H 'content-Type: application/json' -d "payload={\"text\":\"${log_text}\", \"user_ids\":[${push_ChatUSERID}]}" >/dev/null 2>&1
- }
- } &
-}
-croncmd() { #定时任务工具
- if [ -n "$(crontab -h 2>&1 | grep '\-l')" ]; then
- crontab "$1"
- else
- crondir="$(crond -h 2>&1 | grep -oE 'Default:.*' | awk -F ":" '{print $2}')"
- [ ! -w "$crondir" ] && crondir="/etc/storage/cron/crontabs"
- [ ! -w "$crondir" ] && crondir="/var/spool/cron/crontabs"
- [ ! -w "$crondir" ] && crondir="/var/spool/cron"
- if [ -w "$crondir" ]; then
- [ "$1" = "-l" ] && cat "$crondir"/"$USER" 2>/dev/null
- [ -f "$1" ] && cat "$1" >"$crondir"/"$USER"
- else
- echo "你的设备不支持定时任务配置,脚本大量功能无法启用,请尝试使用搜索引擎查找安装方式!"
- fi
- fi
-}
-cronset() { #定时任务设置
- # 参数1代表要移除的关键字,参数2代表要添加的任务语句
- tmpcron="$TMPDIR"/cron_tmp
- croncmd -l >"$tmpcron" 2>/dev/null
- sed -i "/$1/d" "$tmpcron"
- sed -i '/^$/d' "$tmpcron"
- echo "$2" >>"$tmpcron"
- croncmd "$tmpcron"
- rm -f "$tmpcron"
-}
-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
-}
-put_save() { #推送面板选择
- [ -z "$3" ] && request_type=PUT || request_type=$3
- if curl --version >/dev/null 2>&1; then
- curl -sS -X "$request_type" -H "Authorization: Bearer $secret" -H "Content-Type:application/json" "$1" -d "$2" >/dev/null
- elif wget --version >/dev/null 2>&1; then
- wget -q --method="$request_type" --header="Authorization: Bearer $secret" --header="Content-Type:application/json" --body-data="$2" "$1" >/dev/null
- fi
-}
-get_bin() { #专用于项目内部文件的下载
- [ -z "$update_url" ] && update_url=https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@master
- if [ -n "$url_id" ]; then
- echo "$2" | grep -q '^bin/' && release_type=update #/bin文件改为在update分支下载
- echo "$2" | grep -q '^public/' && release_type=dev #/public文件改为在dev分支下载
- [ -z "$release_type" ] && release_type=master
- if [ "$url_id" = 101 -o "$url_id" = 104 ]; then
- url="$(grep "$url_id" "$CRASHDIR"/configs/servers.list | awk '{print $3}')@$release_type/$2" #jsdelivr特殊处理
- else
- url="$(grep "$url_id" "$CRASHDIR"/configs/servers.list | awk '{print $3}')/$release_type/$2"
- fi
- else
- url="$update_url/$2"
- fi
- $0 webget "$1" "$url" "$3" "$4" "$5" "$6"
-}
-mark_time() { #时间戳
- date +%s >"$TMPDIR"/crash_start_time
-}
-getlanip() { #获取局域网host地址
- i=1
- while [ "$i" -le "20" ]; do
- host_ipv4=$(ip a 2>&1 | grep -w 'inet' | grep 'global' | grep 'brd' | grep -Ev 'utun|iot|peer|docker|podman|virbr|vnet|ovs|vmbr|veth|vmnic|vboxnet|lxcbr|xenbr|vEthernet' | grep -E ' 1(92|0|72)\.' | sed 's/.*inet.//g' | sed 's/br.*$//g' | sed 's/metric.*$//g') #ipv4局域网网段
- [ "$ipv6_redir" = "已开启" ] && host_ipv6=$(ip a 2>&1 | grep -w 'inet6' | grep -E 'global' | sed 's/.*inet6.//g' | sed 's/scope.*$//g') #ipv6公网地址段
- [ -f "$TMPDIR"/ShellCrash.log ] && break
- [ -n "$host_ipv4" -a "$ipv6_redir" != "已开启" ] && break
- [ -n "$host_ipv4" -a -n "$host_ipv6" ] && break
- sleep 1 && i=$((i + 1))
- done
- #添加自定义ipv4局域网网段
- if [ "$replace_default_host_ipv4" == "已启用" ]; then
- host_ipv4="$cust_host_ipv4"
- else
- host_ipv4="$host_ipv4$cust_host_ipv4"
- fi
- #缺省配置
- [ -z "$host_ipv4" ] && host_ipv4='192.168.0.0/16 10.0.0.0/12 172.16.0.0/12'
- host_ipv6="fe80::/10 fd00::/8 $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)
- [ -z "$local_ipv4" ] && local_ipv4=$(ip route 2>&1 | grep -Eo 'src.*' | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | sort -u)
- #保留地址
- [ -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"
-}
-parse_singbox_dns() { #singbox的dns分割工具
- first_dns=$(echo "$1" | cut -d',' -f1 | cut -d' ' -f1)
- type=""
- server=""
- port=""
- case "$first_dns" in
- *://*)
- type="${first_dns%%://*}"
- tmp="${first_dns#*://}"
- ;;
- *)
- type="udp"
- tmp="$first_dns"
- ;;
- esac
- case "$tmp" in
- \[*\]*)
- server="${tmp%%]*}"
- server="${server#[}"
- port="${tmp#*\]}"
- port="${port#:}"
- ;;
- *)
- server="${tmp%%[:/]*}"
- port="${tmp#*:}"
- [ "$port" = "$tmp" ] && port=""
- ;;
- esac
- if [ -z "$port" ]; then
- case "$type" in
- udp|tcp) port=53 ;;
- doh|https) port=443 ;;
- dot|tls) port=853 ;;
- *) port=53 ;;
- esac
- fi
- # 输出
- echo '"type": "'"$type"'", "server": "'"$server"'", "server_port": '"$port"','
-}
-urlencode() {
- LC_ALL=C
- printf '%s' "$1" \
- | hexdump -v -e '/1 "%02X\n"' \
- | while read -r hex; do
- case "$hex" in
- 2D|2E|5F|7E|3[0-9]|4[1-9A-F]|5[0-9A]|6[1-9A-F]|7[0-9A-E])
- printf "\\$(printf '%03o' "0x$hex")"
- ;;
- *)
- printf "%%%s" "$hex"
- ;;
- esac
- done
-}
-#配置文件相关
-check_clash_config() { #检查clash配置文件
- #检测节点或providers
- sed -n "/^proxies:/,/^[a-z]/ { /^[a-z]/d; p; }" "$core_config_new" >"$TMPDIR"/proxies.yaml
- if ! grep -Eq 'server:|server":|server'\'':' "$TMPDIR"/proxies.yaml && ! grep -q 'proxy-providers:' "$core_config_new"; then
- echo "-----------------------------------------------"
- logger "获取到了配置文件【$core_config_new】,但似乎并不包含正确的节点信息!" 31
- cat "$TMPDIR"/proxies.yaml
- sleep 1
- echo "-----------------------------------------------"
- echo "请尝试使用6-2或者6-3的方式生成配置文件!"
- exit 1
- fi
- rm -rf "$TMPDIR"/proxies.yaml
- #检测旧格式
- if cat "$core_config_new" | grep 'Proxy Group:' >/dev/null; then
- echo "-----------------------------------------------"
- logger "已经停止对旧格式配置文件的支持!!!" 31
- echo -e "请使用新格式或者使用【在线生成配置文件】功能!"
- echo "-----------------------------------------------"
- exit 1
- fi
- #检测不支持的加密协议
- if cat "$core_config_new" | grep 'cipher: chacha20,' >/dev/null; then
- echo "-----------------------------------------------"
- logger "已停止支持chacha20加密,请更换更安全的节点加密协议!" 31
- echo "-----------------------------------------------"
- exit 1
- fi
- #检测并去除无效策略组
- [ -n "$url_type" ] && ckcmd xargs && {
- cat "$core_config_new" | sed '/^rules:/,$d' | grep -A 15 "\- name:" | xargs | sed 's/- name: /\n/g' | sed 's/ type: .*proxies: /#/g' | sed 's/- //g' | grep -E '#DIRECT $|#DIRECT$' | grep -Ev '全球直连|direct|Direct' | awk -F '#' '{print $1}' >"$TMPDIR"/clash_proxies_$USER
- while read line; do
- sed -i "/- $line/d" "$core_config_new"
- sed -i "/- name: $line/,/- DIRECT/d" "$core_config_new"
- done <"$TMPDIR"/clash_proxies_$USER
- rm -rf "$TMPDIR"/clash_proxies_$USER
- }
-}
-check_singbox_config() { #检查singbox配置文件
- #检测节点或providers
- if ! grep -qE '"(socks|http|shadowsocks(r)?|vmess|trojan|wireguard|hysteria(2)?|vless|shadowtls|tuic|ssh|tor|providers|anytls|soduku)"' "$core_config_new"; then
- echo "-----------------------------------------------"
- logger "获取到了配置文件【$core_config_new】,但似乎并不包含正确的节点信息!" 31
- echo "请尝试使用6-2或者6-3的方式生成配置文件!"
- exit 1
- fi
- #删除不兼容的旧版内容
- [ "$(wc -l <"$core_config_new")" -lt 3 ] && {
- sed -i 's/^.*"inbounds":/{"inbounds":/' "$core_config_new"
- sed -i 's/{[^{}]*"dns-out"[^{}]*}//g' "$core_config_new"
- }
- #检查不支持的旧版内容
- grep -q '"sni"' "$core_config_new" && {
- logger "获取到了不支持的旧版(<1.12)配置文件【$core_config_new】!" 31
- echo "请尝试使用支持1.12以上版本内核的方式生成配置文件!"
- exit 1
- }
- #检测并去除无效策略组
- [ -n "$url_type" ] && {
- #获得无效策略组名称
- grep -oE '\{"type":"urltest","tag":"[^"]*","outbounds":\["DIRECT"\]' "$core_config_new" | sed -n 's/.*"tag":"\([^"]*\)".*/\1/p' >"$TMPDIR"/singbox_tags
- #删除策略组
- sed -i 's/{"type":"urltest","tag":"[^"]*","outbounds":\["DIRECT"\]}//g; s/{"type":"[^"]*","tag":"[^"]*","outbounds":\["DIRECT"\],"url":"[^"]*","interval":"[^"]*","tolerance":[^}]*}//g' "$core_config_new"
- #删除全部包含策略组名称的规则
- while read line; do
- sed -i "s/\"$line\"//g" "$core_config_new"
- done <"$TMPDIR"/singbox_tags
- rm -rf "$TMPDIR"/singbox_tags
- }
- #清理多余逗号
- sed -i 's/,\+/,/g; s/\[,/\[/g; s/,]/]/g' "$core_config_new"
-}
-update_servers() { #更新servers.list
- get_bin "$TMPDIR"/servers.list public/servers.list
- [ "$?" = 0 ] && mv -f "$TMPDIR"/servers.list "$CRASHDIR"/configs/servers.list
-}
-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}')
- #如果传来的是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
- Https="${Server}/sub?target=${target}&${Server_ua}=${user_agent}&insert=true&new_name=true&scv=true&udp=true&${urlencodeUrl}"
- url_type=true
- fi
- #输出
- echo "-----------------------------------------------"
- logger 正在连接服务器获取【${target}】配置文件…………
- echo -e "链接地址为:\033[4;32m$Https\033[0m"
- echo 可以手动复制该链接到浏览器打开并查看数据是否正常!
- #获取在线config文件
- core_config_new="$TMPDIR"/${target}_config.${format}
- rm -rf ${core_config_new}
- $0 webget "$core_config_new" "$Https" echoon rediron skipceron "$user_agent"
- if [ "$?" != "0" ]; then
- if [ -z "$url_type" ]; then
- echo "-----------------------------------------------"
- logger "配置文件获取失败!" 31
- echo -e "\033[31m请尝试使用【在线生成配置文件】功能!\033[0m"
- echo "-----------------------------------------------"
- exit 1
- else
- if [ -n "$retry" ] && [ "$retry" -ge 3 ]; then
- logger "无法获取配置文件,请检查链接格式以及网络连接状态!" 31
- echo -e "\033[32m也可用浏览器下载以上链接后,使用WinSCP手动上传到/tmp目录后执行crash命令本地导入!\033[0m"
- exit 1
- else
- retry=$((retry + 1))
- logger "配置文件获取失败!" 31
- if [ "$retry" = 1 ]; then
- echo -e "\033[32m尝试更新服务器列表并使用其他服务器获取配置!\033[0m"
- update_servers
- else
- echo -e "\033[32m尝试使用其他服务器获取配置!\033[0m"
- fi
- echo -e "正在重试\033[33m第$retry次/共3次!\033[0m"
- if [ "$server_link" -ge 4 ]; then
- server_link=0
- fi
- server_link=$((server_link + 1))
- setconfig server_link $server_link
- Https=""
- get_core_config
- fi
- fi
- else
- Https=""
- if echo "$crashcore" | grep -q 'singbox'; then
- check_singbox_config
- else
- check_clash_config
- fi
- #如果不同则备份并替换文件
- if [ -s $core_config ]; then
- compare $core_config_new $core_config
- [ "$?" = 0 ] || mv -f $core_config $core_config.bak && mv -f $core_config_new $core_config
- else
- mv -f $core_config_new $core_config
- fi
- echo -e "\033[32m已成功获取配置文件!\033[0m"
- fi
- return 0
-}
-modify_yaml() { #修饰clash配置文件
- ##########需要变更的配置###########
- [ -z "$skip_cert" ] && skip_cert=已开启
- [ "$ipv6_dns" = "已开启" ] && dns_v6='true' || dns_v6='false'
- external="external-controller: 0.0.0.0:$db_port"
- if [ "$redir_mod" = "混合模式" -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
- tun='tun: {enable: false}'
- fi
- 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"'
- }
- #dns配置
- [ -z "$(cat "$CRASHDIR"/yamls/user.yaml 2>/dev/null | grep '^dns:')" ] && {
- [ "$crashcore" != meta ] && dns_resolver='223.5.5.5'
- cat >"$TMPDIR"/dns.yaml </dev/null | grep -v '#' | sed "s/^/ - '/" | sed "s/$/'/" >>"$TMPDIR"/dns.yaml
- else
- echo " - '+.*'" >>"$TMPDIR"/dns.yaml #使用fake-ip模拟redir_host
- fi
- #mix模式fakeip绕过cn
- [ "$dns_mod" = "mix" ] && echo ' - "rule-set:cn"' >>"$TMPDIR"/dns.yaml
- #mix模式和route模式插入分流设置
- if [ "$dns_mod" = "mix" ] || [ "$dns_mod" = "route" ]; then
- [ "$dns_protect" != "OFF" ] && dns_final="$dns_fallback" || dns_final="$dns_nameserver"
- cat >>"$TMPDIR"/dns.yaml <>"$TMPDIR"/dns.yaml <"$TMPDIR"/set.yaml </dev/null)" ]; then
- #NTP劫持
- cat >"$TMPDIR"/hosts.yaml <>"$TMPDIR"/hosts.yaml
- else
- #加载本机hosts
- sys_hosts=/etc/hosts
- [ -f /data/etc/custom_hosts ] && sys_hosts=/data/etc/custom_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 <$sys_hosts
- fi
- fi
- #分割配置文件
- yaml_char='proxies proxy-groups proxy-providers rules rule-providers sub-rules listeners'
- for char in $yaml_char; do
- sed -n "/^$char:/,/^[a-z]/ { /^[a-z]/d; p; }" $core_config >"$TMPDIR"/${char}.yaml
- done
- #跳过本地tls证书验证
- [ "$skip_cert" = "已开启" ] && sed -i 's/skip-cert-verify: false/skip-cert-verify: true/' "$TMPDIR"/proxies.yaml ||
- sed -i 's/skip-cert-verify: true/skip-cert-verify: false/' "$TMPDIR"/proxies.yaml
- #插入自定义策略组
- sed -i "/#自定义策略组开始/,/#自定义策略组结束/d" "$TMPDIR"/proxy-groups.yaml
- sed -i "/#自定义策略组/d" "$TMPDIR"/proxy-groups.yaml
- [ -n "$(grep -Ev '^#' "$CRASHDIR"/yamls/proxy-groups.yaml 2>/dev/null)" ] && {
- #获取空格数
- space_name=$(grep -aE '^ *- \{?name: ' "$TMPDIR"/proxy-groups.yaml | head -n 1 | grep -oE '^ *')
- space_proxy="$space_name "
- #合并自定义策略组到proxy-groups.yaml
- cat "$CRASHDIR"/yamls/proxy-groups.yaml | sed "/^#/d" | sed "s/#.*//g" | sed '1i\ #自定义策略组开始' | sed '$a\ #自定义策略组结束' | sed "s/^ */${space_name} /g" | sed "s/^ *- /${space_proxy}- /g" | sed "s/^ *- name: /${space_name}- name: /g" | sed "s/^ *- {name: /${space_name}- {name: /g" >"$TMPDIR"/proxy-groups_add.yaml
- cat "$TMPDIR"/proxy-groups.yaml >>"$TMPDIR"/proxy-groups_add.yaml
- mv -f "$TMPDIR"/proxy-groups_add.yaml "$TMPDIR"/proxy-groups.yaml
- oldIFS="$IFS"
- grep "\- name: " "$CRASHDIR"/yamls/proxy-groups.yaml | sed "/^#/d" | while read line; do #将自定义策略组插入现有的proxy-group
- new_group=$(echo $line | grep -Eo '^ *- name:.*#' | cut -d'#' -f1 | sed 's/.*name: //g')
- proxy_groups=$(echo $line | grep -Eo '#.*' | sed "s/#//")
- IFS="#"
- for name in $proxy_groups; do
- line_a=$(grep -n "\- name: $name" "$TMPDIR"/proxy-groups.yaml | head -n 1 | awk -F: '{print $1}') #获取group行号
- [ -n "$line_a" ] && {
- line_b=$(grep -A 8 "\- name: $name" "$TMPDIR"/proxy-groups.yaml | grep -n "proxies:$" | head -n 1 | awk -F: '{print $1}') #获取proxies行号
- line_c=$((line_a + line_b - 1)) #计算需要插入的行号
- space=$(sed -n "$((line_c + 1))p" "$TMPDIR"/proxy-groups.yaml | grep -oE '^ *') #获取空格数
- [ "$line_c" -gt 2 ] && sed -i "${line_c}a\\${space}- ${new_group} #自定义策略组" "$TMPDIR"/proxy-groups.yaml
- }
- done
- IFS="$oldIFS"
- done
- }
- #插入自定义代理
- sed -i "/#自定义代理/d" "$TMPDIR"/proxies.yaml
- sed -i "/#自定义代理/d" "$TMPDIR"/proxy-groups.yaml
- [ -n "$(grep -Ev '^#' "$CRASHDIR"/yamls/proxies.yaml 2>/dev/null)" ] && {
- space_proxy=$(cat "$TMPDIR"/proxies.yaml | grep -aE '^ *- ' | head -n 1 | grep -oE '^ *') #获取空格数
- cat "$CRASHDIR"/yamls/proxies.yaml | sed "s/^ *- /${space_proxy}- /g" | sed "/^#/d" | sed "/^ *$/d" | sed 's/#.*/ #自定义代理/g' >>"$TMPDIR"/proxies.yaml #插入节点
- oldIFS="$IFS"
- cat "$CRASHDIR"/yamls/proxies.yaml | sed "/^#/d" | while read line; do #将节点插入proxy-group
- proxy_name=$(echo $line | grep -Eo 'name: .+, ' | cut -d',' -f1 | sed 's/name: //g')
- proxy_groups=$(echo $line | grep -Eo '#.*' | sed "s/#//")
- IFS="#"
- for name in $proxy_groups; do
- line_a=$(grep -n "\- name: $name" "$TMPDIR"/proxy-groups.yaml | head -n 1 | awk -F: '{print $1}') #获取group行号
- [ -n "$line_a" ] && {
- line_b=$(grep -A 8 "\- name: $name" "$TMPDIR"/proxy-groups.yaml | grep -n "proxies:$" | head -n 1 | awk -F: '{print $1}') #获取proxies行号
- line_c=$((line_a + line_b - 1)) #计算需要插入的行号
- space=$(sed -n "$((line_c + 1))p" "$TMPDIR"/proxy-groups.yaml | grep -oE '^ *') #获取空格数
- [ "$line_c" -gt 2 ] && sed -i "${line_c}a\\${space}- ${proxy_name} #自定义代理" "$TMPDIR"/proxy-groups.yaml
- }
- done
- IFS="$oldIFS"
- done
- }
- #节点绕过功能支持
- sed -i "/#节点绕过/d" "$TMPDIR"/rules.yaml
- [ "$proxies_bypass" = "已启用" ] && {
- cat "$TMPDIR"/proxies.yaml | sed '/^proxy-/,$d' | sed '/^rule-/,$d' | grep -v '^\s*#' | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | awk '!a[$0]++' | sed 's/^/\ -\ IP-CIDR,/g' | sed 's|$|/32,DIRECT,no-resolve #节点绕过|g' >>"$TMPDIR"/proxies_bypass
- cat "$TMPDIR"/proxies.yaml | sed '/^proxy-/,$d' | sed '/^rule-/,$d' | grep -v '^\s*#' | grep -vE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -oE '[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?' | awk '!a[$0]++' | sed 's/^/\ -\ DOMAIN,/g' | sed 's/$/,DIRECT #节点绕过/g' >>"$TMPDIR"/proxies_bypass
- cat "$TMPDIR"/rules.yaml >>"$TMPDIR"/proxies_bypass
- mv -f "$TMPDIR"/proxies_bypass "$TMPDIR"/rules.yaml
- }
- #插入自定义规则
- sed -i "/#自定义规则/d" "$TMPDIR"/rules.yaml
- [ -s "$CRASHDIR"/yamls/rules.yaml ] && {
- cat "$CRASHDIR"/yamls/rules.yaml | sed "/^#/d" | sed '$a\' | sed 's/$/ #自定义规则/g' >"$TMPDIR"/rules.add
- cat "$TMPDIR"/rules.yaml >>"$TMPDIR"/rules.add
- mv -f "$TMPDIR"/rules.add "$TMPDIR"/rules.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
- }
- #对齐rules中的空格
- sed -i 's/^ *-/ -/g' "$TMPDIR"/rules.yaml
- #合并文件
- [ -s "$CRASHDIR"/yamls/user.yaml ] && {
- yaml_user="$CRASHDIR"/yamls/user.yaml
- #set和user去重,且优先使用user.yaml
- cp -f "$TMPDIR"/set.yaml "$TMPDIR"/set_bak.yaml
- for char in mode allow-lan log-level tun experimental external-ui-url interface-name dns store-selected; do
- [ -n "$(grep -E "^$char" $yaml_user)" ] && sed -i "/^$char/d" "$TMPDIR"/set.yaml
- done
- }
- [ -s "$TMPDIR"/dns.yaml ] && yaml_dns="$TMPDIR"/dns.yaml
- [ -s "$TMPDIR"/hosts.yaml ] && yaml_hosts="$TMPDIR"/hosts.yaml
- [ -s "$CRASHDIR"/yamls/others.yaml ] && yaml_others="$CRASHDIR"/yamls/others.yaml
- yaml_add=
- for char in $yaml_char; do #将额外配置文件合并
- [ -s "$TMPDIR"/${char}.yaml ] && {
- sed -i "1i\\${char}:" "$TMPDIR"/${char}.yaml
- yaml_add="$yaml_add "$TMPDIR"/${char}.yaml"
- }
- done
- #合并完整配置文件
- cut -c 1- "$TMPDIR"/set.yaml $yaml_dns $yaml_hosts $yaml_user $yaml_others $yaml_add >"$TMPDIR"/config.yaml
- #测试自定义配置文件
- "$TMPDIR"/CrashCore -t -d "$BINDIR" -f "$TMPDIR"/config.yaml >/dev/null
- if [ "$?" != 0 ]; then
- logger "$("$TMPDIR"/CrashCore -t -d "$BINDIR" -f "$TMPDIR"/config.yaml | grep -Eo 'error.*=.*')" 31
- logger "自定义配置文件校验失败!将使用基础配置文件启动!" 33
- logger "错误详情请参考 "$TMPDIR"/error.yaml 文件!" 33
- mv -f "$TMPDIR"/config.yaml "$TMPDIR"/error.yaml >/dev/null 2>&1
- sed -i "/#自定义策略组开始/,/#自定义策略组结束/d" "$TMPDIR"/proxy-groups.yaml
- mv -f "$TMPDIR"/set_bak.yaml "$TMPDIR"/set.yaml >/dev/null 2>&1
- #合并基础配置文件
- cut -c 1- "$TMPDIR"/set.yaml $yaml_dns $yaml_add >"$TMPDIR"/config.yaml
- sed -i "/#自定义/d" "$TMPDIR"/config.yaml
- fi
- #建立软连接
- [ ""$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
-}
-modify_json() { #修饰singbox1.13配置文件
- #提取配置文件以获得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
- cat "$TMPDIR"/format.json | sed -n '/"outbounds":/,/^ "[a-z]/p' | sed '$d' >>"$TMPDIR"/jsons/outbounds.json
- [ "$crashcore" = "singboxr" ] && {
- echo '{' >"$TMPDIR"/jsons/providers.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
- #生成log.json
- cat >"$TMPDIR"/jsons/log.json <"$TMPDIR"/jsons/add_hosts.json </dev/null | grep -Ev '#|\*|\+|Mijia' | sed '/^\s*$/d' | awk '{printf "\"%s\", ",$1}' | sed 's/, $//')
- fake_ip_filter_suffix=$(cat ${CRASHDIR}/configs/fake_ip_filter ${CRASHDIR}/configs/fake_ip_filter.list 2>/dev/null | grep -v '.\*' | grep -E '\*|\+' | sed 's/^[*+]\.//' | awk '{printf "\"%s\", ",$1}' | sed 's/, $//')
- fake_ip_filter_regex=$(cat ${CRASHDIR}/configs/fake_ip_filter ${CRASHDIR}/configs/fake_ip_filter.list 2>/dev/null | grep '.\*' | sed 's/\./\\\\./g' | sed 's/\*/.\*/' | sed 's/^+/.\+/' | awk '{printf "\"%s\", ",$1}' | sed 's/, $//')
- [ -n "$fake_ip_filter_domain" ] && fake_ip_filter_domain="{ \"domain\": [$fake_ip_filter_domain], \"server\": \"dns_direct\" },"
- [ -n "$fake_ip_filter_suffix" ] && fake_ip_filter_suffix="{ \"domain_suffix\": [$fake_ip_filter_suffix], \"server\": \"dns_direct\" },"
- [ -n "$fake_ip_filter_regex" ] && fake_ip_filter_regex="{ \"domain_regex\": [$fake_ip_filter_regex], \"server\": \"dns_direct\" },"
- proxy_dns='{ "query_type": ["A", "AAAA"], "server": "dns_fakeip", "strategy": "'"$strategy"'", "rewrite_ttl": 1 }'
- #mix模式插入fakeip过滤规则
- [ "$dns_mod" = "mix" ] && direct_dns='{ "rule_set": ["cn"], "server": "dns_direct" },'
- }
- [ "$dns_mod" = "route" ] && {
- global_dns=dns_proxy
- direct_dns='{ "rule_set": ["cn"], "server": "dns_direct" }'
- }
- #防泄露设置
- [ "$dns_protect" = "OFF" ] && sed -i 's/"server": "dns_proxy"/"server": "dns_direct"/g' "$TMPDIR"/jsons/route.json
- #生成add_rule_set.json
- [ "$dns_mod" = "mix" ] || [ "$dns_mod" = "route" ] &&
- ! grep -Eq '"tag" *:[[:space:]]*"cn"' "$CRASHDIR"/jsons/*.json &&
- cat >"$TMPDIR"/jsons/add_rule_set.json <"$TMPDIR"/jsons/dns.json <"$TMPDIR"/jsons/add_route.json <"$TMPDIR"/jsons/certificate.json <"$TMPDIR"/jsons/inbounds.json <>"$TMPDIR"/jsons/tun.json <"$TMPDIR"/jsons/add_outbounds.json <"$TMPDIR"/jsons/experimental.json </dev/null)" ] && {
- cat "$CRASHDIR"/yamls/rules.yaml |
- sed '/#.*/d' |
- sed 's/,no-resolve//g' |
- grep -oE '\-.*,.*,.*' |
- sed 's/- DOMAIN-SUFFIX,/{ "domain_suffix": [ "/g' |
- sed 's/- DOMAIN-KEYWORD,/{ "domain_keyword": [ "/g' |
- sed 's/- IP-CIDR,/{ "ip_cidr": [ "/g' |
- sed 's/- SRC-IP-CIDR,/{ "._ip_cidr": [ "/g' |
- sed 's/- DST-PORT,/{ "port": [ "/g' |
- sed 's/- SRC-PORT,/{ "._port": [ "/g' |
- sed 's/- GEOIP,/{ "geoip": [ "/g' |
- sed 's/- GEOSITE,/{ "geosite": [ "/g' |
- sed 's/- IP-CIDR6,/{ "ip_cidr": [ "/g' |
- sed 's/- DOMAIN,/{ "domain": [ "/g' |
- sed 's/- PROCESS-NAME,/{ "process_name": [ "/g' |
- sed 's/,/" ], "outbound": "/g' |
- sed 's/$/" },/g' |
- sed '1i\{ "route": { "rules": [ ' |
- sed '$s/,$/ ] } }/' >"$TMPDIR"/jsons/cust_add_rules.json
- [ ! -s "$TMPDIR"/jsons/cust_add_rules.json ] && rm -rf "$TMPDIR"/jsons/cust_add_rules.json
- }
- #清理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
- #跳过本地tls证书验证
- if [ -z "$skip_cert" -o "$skip_cert" = "已开启" ]; then
- sed -i 's/"insecure": false/"insecure": true/' "$TMPDIR"/jsons/outbounds.json "$TMPDIR"/jsons/providers.json 2>/dev/null
- else
- sed -i 's/"insecure": true/"insecure": false/' "$TMPDIR"/jsons/outbounds.json "$TMPDIR"/jsons/providers.json 2>/dev/null
- fi
- #判断可用并修饰outbounds&providers&route.json结尾
- for file in outbounds providers route; do
- if [ -n "$(grep ${file} "$TMPDIR"/jsons/${file}.json 2>/dev/null)" ]; then
- sed -i 's/^ },$/ }/; s/^ ],$/ ]/' "$TMPDIR"/jsons/${file}.json
- echo '}' >>"$TMPDIR"/jsons/${file}.json
- else
- rm -rf "$TMPDIR"/jsons/${file}.json
- fi
- done
- #加载自定义配置文件
- mkdir -p "$TMPDIR"/jsons_base
- #以下为覆盖脚本的自定义文件
- for char in log dns ntp certificate 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 #如果重复则临时备份
- }
- done
- #以下为增量添加的自定义文件
- for char in others endpoints inbounds outbounds providers route services; do
- [ -s "$CRASHDIR"/jsons/${char}.json ] && {
- ln -sf "$CRASHDIR"/jsons/${char}.json "$TMPDIR"/jsons/cust_${char}.json
- }
- done
- #测试自定义配置文件
- 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')
- [ "$error_file" = 'add_rules.json' ] && error_file="$CRASHDIR"/yamls/rules.yaml自定义规则 || error_file="$CRASHDIR"/jsons/$error_file
- logger "自定义配置文件校验失败,请检查【${error_file}】文件!" 31
- logger "尝试使用基础配置文件启动~" 33
- #清理自定义配置文件并还原基础配置
- rm -rf "$TMPDIR"/jsons/cust_*
- mv -f "$TMPDIR"/jsons_base/* "$TMPDIR"/jsons 2>/dev/null
- fi
- #清理缓存
- rm -rf "$TMPDIR"/*.json
- rm -rf "$TMPDIR"/jsons_base
- return 0
-}
-
-#设置路由规则
-cn_ip_route() { #CN-IP绕过
- ckgeo cn_ip.txt china_ip_list.txt
- [ -f "$BINDIR"/cn_ip.txt ] && [ "$firewall_mod" = iptables ] && {
- # see https://raw.githubusercontent.com/Hackl0us/GeoIP2-CN/release/CN-ip-cidr.txt
- echo "create cn_ip hash:net family inet hashsize 10240 maxelem 10240" >"$TMPDIR"/cn_ip.ipset
- awk '!/^$/&&!/^#/{printf("add cn_ip %s'" "'\n",$0)}' "$BINDIR"/cn_ip.txt >>"$TMPDIR"/cn_ip.ipset
- ipset destroy cn_ip >/dev/null 2>&1
- ipset -! restore <"$TMPDIR"/cn_ip.ipset
- rm -rf "$TMPDIR"/cn_ip.ipset
- }
-}
-cn_ipv6_route() { #CN-IPV6绕过
- ckgeo cn_ipv6.txt china_ipv6_list.txt
- [ -f "$BINDIR"/cn_ipv6.txt ] && [ "$firewall_mod" = iptables ] && {
- #ipv6
- #see https://ispip.clang.cn/all_cn_ipv6.txt
- echo "create cn_ip6 hash:net family inet6 hashsize 5120 maxelem 5120" >"$TMPDIR"/cn_ipv6.ipset
- awk '!/^$/&&!/^#/{printf("add cn_ip6 %s'" "'\n",$0)}' "$BINDIR"/cn_ipv6.txt >>"$TMPDIR"/cn_ipv6.ipset
- ipset destroy cn_ip6 >/dev/null 2>&1
- ipset -! restore <"$TMPDIR"/cn_ipv6.ipset
- rm -rf "$TMPDIR"/cn_ipv6.ipset
- }
-}
-start_ipt_route() { #iptables-route通用工具
- #$1:iptables/ip6tables $2:所在的表(nat/mangle) $3:所在的链(OUTPUT/PREROUTING) $4:新创建的shellcrash链表 $5:tcp/udp/all
- #区分ipv4/ipv6
- [ "$1" = 'iptables' ] && {
- RESERVED_IP=$reserve_ipv4
- HOST_IP=$host_ipv4
- [ "$3" = 'OUTPUT' ] && HOST_IP="127.0.0.0/8 $local_ipv4"
- [ "$4" = 'shellcrash_vm' ] && HOST_IP="$vm_ipv4"
- iptables -h | grep -q '\-w' && w='-w' || w=''
- }
- [ "$1" = 'ip6tables' ] && {
- RESERVED_IP=$reserve_ipv6
- HOST_IP=$host_ipv6
- [ "$3" = 'OUTPUT' ] && HOST_IP="::1 $host_ipv6"
- ip6tables -h | grep -q '\-w' && w='-w' || w=''
- }
- #创建新的shellcrash链表
- $1 $w -t $2 -N $4
- #过滤dns
- $1 $w -t $2 -A $4 -p tcp --dport 53 -j RETURN
- $1 $w -t $2 -A $4 -p udp --dport 53 -j RETURN
- #防回环
- $1 $w -t $2 -A $4 -m mark --mark $routing_mark -j RETURN
- [ "$3" = 'OUTPUT' ] && for gid in 453 7890; do
- $1 $w -t $2 -A $4 -m owner --gid-owner $gid -j RETURN
- 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
- #跳过目标保留地址及目标本机网段
- for ip in $HOST_IP $RESERVED_IP; do
- $1 $w -t $2 -A $4 -d $ip -j RETURN
- done
- #绕过CN_IP
- [ "$1" = iptables ] && [ "$dns_mod" != "fake-ip" ] && [ "$cn_ip_route" = "已开启" ] && [ -f "$BINDIR"/cn_ip.txt ] && $1 $w -t $2 -A $4 -m set --match-set cn_ip dst -j RETURN 2>/dev/null
- [ "$1" = ip6tables ] && [ "$dns_mod" != "fake-ip" ] && [ "$cn_ipv6_route" = "已开启" ] && [ -f "$BINDIR"/cn_ipv6.txt ] && $1 $w -t $2 -A $4 -m set --match-set cn_ip6 dst -j RETURN 2>/dev/null
- #局域网mac地址黑名单过滤
- [ "$3" = 'PREROUTING' ] && [ "$macfilter_type" != "白名单" ] && {
- [ -s "$CRASHDIR"/configs/mac ] &&
- for mac in $(cat "$CRASHDIR"/configs/mac); do
- $1 $w -t $2 -A $4 -m mac --mac-source $mac -j RETURN
- done
- [ -s "$CRASHDIR"/configs/ip_filter ] && [ "$1" = 'iptables' ] &&
- for ip in $(cat "$CRASHDIR"/configs/ip_filter); do
- $1 $w -t $2 -A $4 -s $ip -j RETURN
- done
- }
- #tcp&udp分别进代理链
- proxy_set() {
- if [ "$3" = 'PREROUTING' ] && [ "$4" != 'shellcrash_vm' ] && [ "$macfilter_type" = "白名单" ] && [ -n "$(cat $CRASHDIR/configs/mac $CRASHDIR/configs/ip_filter 2>/dev/null)" ]; then
- [ -s "$CRASHDIR"/configs/mac ] &&
- for mac in $(cat "$CRASHDIR"/configs/mac); do
- $1 $w -t $2 -A $4 -p $5 -m mac --mac-source $mac -j $JUMP
- done
- [ -s "$CRASHDIR"/configs/ip_filter ] && [ "$1" = 'iptables' ] &&
- for ip in $(cat "$CRASHDIR"/configs/ip_filter); do
- $1 $w -t $2 -A $4 -p $5 -s $ip -j $JUMP
- done
- else
- for ip in $HOST_IP; do #仅限指定网段流量
- $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" = "已开启" ] && [ "$1" = iptables ] && $1 $w -t $2 -I $3 -p $5 -d 28.0.0.0/8 -j $4
- [ "$dns_mod" = "mix" -o "$dns_mod" = "fake-ip" ] && [ "$common_ports" = "已开启" ] && [ "$1" = ip6tables ] && $1 $w -t $2 -I $3 -p $5 -d fc00::/16 -j $4
- }
- [ "$5" = "tcp" -o "$5" = "all" ] && proxy_set $1 $2 $3 $4 tcp
- [ "$5" = "udp" -o "$5" = "all" ] && proxy_set $1 $2 $3 $4 udp
-}
-start_ipt_dns() { #iptables-dns通用工具
- #$1:iptables/ip6tables $2:所在的表(OUTPUT/PREROUTING) $3:新创建的shellcrash表
- #区分ipv4/ipv6
- [ "$1" = 'iptables' ] && {
- HOST_IP="$host_ipv4"
- [ "$2" = 'OUTPUT' ] && HOST_IP="127.0.0.0/8 $local_ipv4"
- [ "$3" = 'shellcrash_vm_dns' ] && HOST_IP="$vm_ipv4"
- iptables -h | grep -q '\-w' && w='-w' || w=''
- }
- [ "$1" = 'ip6tables' ] && {
- HOST_IP=$host_ipv6
- ip6tables -h | grep -q '\-w' && w='-w' || w=''
- }
- $1 $w -t nat -N $3
- #防回环
- $1 $w -t nat -A $3 -m mark --mark $routing_mark -j RETURN
- [ "$2" = 'OUTPUT' ] && for gid in 453 7890; do
- $1 $w -t nat -A $3 -m owner --gid-owner $gid -j RETURN
- done
- [ "$firewall_area" = 5 ] && {
- $1 $w -t nat -A $3 -p tcp -s $bypass_host -j RETURN
- $1 $w -t nat -A $3 -p udp -s $bypass_host -j RETURN
- }
- #局域网mac地址黑名单过滤
- [ "$2" = 'PREROUTING' ] && [ "$macfilter_type" != "白名单" ] && {
- [ -s "$CRASHDIR"/configs/mac ] &&
- for mac in $(cat "$CRASHDIR"/configs/mac); do
- $1 $w -t nat -A $3 -m mac --mac-source $mac -j RETURN
- done
- [ -s "$CRASHDIR"/configs/ip_filter ] && [ "$1" = 'iptables' ] &&
- for ip in $(cat "$CRASHDIR"/configs/ip_filter); do
- $1 $w -t nat -A $3 -s $ip -j RETURN
- done
- }
- if [ "$2" = 'PREROUTING' ] && [ "$3" != 'shellcrash_vm_dns' ] && [ "$macfilter_type" = "白名单" ] && [ -n "$(cat $CRASHDIR/configs/mac $CRASHDIR/configs/ip_filter 2>/dev/null)" ]; then
- [ -s "$CRASHDIR"/configs/mac ] &&
- for mac in $(cat "$CRASHDIR"/configs/mac); do
- $1 $w -t nat -A $3 -p tcp -m mac --mac-source $mac -j REDIRECT --to-ports $dns_port
- $1 $w -t nat -A $3 -p udp -m mac --mac-source $mac -j REDIRECT --to-ports $dns_port
- done
- [ -s "$CRASHDIR"/configs/ip_filter ] && [ "$1" = 'iptables' ] &&
- for ip in $(cat "$CRASHDIR"/configs/ip_filter); do
- $1 $w -t nat -A $3 -p tcp -s $ip -j REDIRECT --to-ports $dns_port
- $1 $w -t nat -A $3 -p udp -s $ip -j REDIRECT --to-ports $dns_port
- done
- else
- for ip in $HOST_IP; do #仅限指定网段流量
- $1 $w -t nat -A $3 -p tcp -s $ip -j REDIRECT --to-ports $dns_port
- $1 $w -t nat -A $3 -p udp -s $ip -j REDIRECT --to-ports $dns_port
- done
- fi
- [ "$1" = 'ip6tables' ] && { #屏蔽外部请求
- $1 $w -t nat -A $3 -p tcp -j RETURN
- $1 $w -t nat -A $3 -p udp -j RETURN
- }
- $1 $w -t nat -I $2 -p tcp --dport 53 -j $3
- $1 $w -t nat -I $2 -p udp --dport 53 -j $3
-}
-start_ipt_wan() { #iptables公网防火墙
- #获取局域网host地址
- getlanip
- if [ "$public_support" = "已开启" ]; then
- $iptable -I INPUT -p tcp --dport $db_port -j ACCEPT
- ckcmd ip6tables && $ip6table -I INPUT -p tcp --dport $db_port -j ACCEPT
- else
- #仅允许非公网设备访问面板
- for ip in $reserve_ipv4; do
- $iptable -A INPUT -p tcp -s $ip --dport $db_port -j ACCEPT
- done
- $iptable -A INPUT -p tcp --dport $db_port -j REJECT
- ckcmd ip6tables && $ip6table -A INPUT -p tcp --dport $db_port -j REJECT
- fi
- if [ "$public_mixport" = "已开启" ]; then
- $iptable -I INPUT -p tcp --dport $mix_port -j ACCEPT
- ckcmd ip6tables && $ip6table -I INPUT -p tcp --dport $mix_port -j ACCEPT
- else
- #仅允许局域网设备访问混合端口
- for ip in $reserve_ipv4; do
- $iptable -A INPUT -p tcp -s $ip --dport $mix_port -j ACCEPT
- done
- $iptable -A INPUT -p tcp --dport $mix_port -j REJECT
- ckcmd ip6tables && $ip6table -A INPUT -p tcp --dport $mix_port -j REJECT
- fi
- $iptable -I INPUT -p tcp -d 127.0.0.1 -j ACCEPT #本机请求全放行
-}
-start_iptables() { #iptables配置总入口
- #启动公网访问防火墙
- start_ipt_wan
- #分模式设置流量劫持
- [ "$redir_mod" = "Redir模式" -o "$redir_mod" = "混合模式" ] && {
- JUMP="REDIRECT --to-ports $redir_port" #跳转劫持的具体命令
- [ "$lan_proxy" = true ] && {
- start_ipt_route iptables nat PREROUTING shellcrash tcp #ipv4-局域网tcp转发
- [ "$ipv6_redir" = "已开启" ] && {
- if $ip6table -j REDIRECT -h 2>/dev/null | grep -q '\--to-ports'; then
- start_ipt_route ip6tables nat PREROUTING shellcrashv6 tcp #ipv6-局域网tcp转发
- else
- logger "当前设备内核缺少ip6tables_REDIRECT模块支持,已放弃启动相关规则!" 31
- fi
- }
- }
- [ "$local_proxy" = true ] && {
- start_ipt_route iptables nat OUTPUT shellcrash_out tcp #ipv4-本机tcp转发
- [ "$ipv6_redir" = "已开启" ] && {
- if $ip6table -j REDIRECT -h 2>/dev/null | grep -q '\--to-ports'; then
- start_ipt_route ip6tables nat OUTPUT shellcrashv6_out tcp #ipv6-本机tcp转发
- else
- logger "当前设备内核缺少ip6tables_REDIRECT模块支持,已放弃启动相关规则!" 31
- fi
- }
- }
- }
- [ "$redir_mod" = "Tproxy模式" ] && {
- modprobe xt_TPROXY >/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
- [ "$lan_proxy" = true ] && start_ipt_route iptables mangle PREROUTING shellcrash_mark all
- [ "$local_proxy" = true ] && {
- if [ -n "$(grep -E '^MARK$' /proc/net/ip_tables_targets)" ]; then
- JUMP="MARK --set-mark $fwmark" #跳转劫持的具体命令
- start_ipt_route iptables mangle OUTPUT shellcrash_mark_out all
- $iptable -t mangle -A PREROUTING -m mark --mark $fwmark -p tcp -j TPROXY --on-port $tproxy_port
- $iptable -t mangle -A PREROUTING -m mark --mark $fwmark -p udp -j TPROXY --on-port $tproxy_port
- else
- logger "当前设备内核可能缺少xt_mark模块支持,已放弃启动本机代理相关规则!" 31
- fi
- }
- else
- logger "当前设备内核可能缺少kmod_ipt_tproxy模块支持,已放弃启动相关规则!" 31
- fi
- [ "$ipv6_redir" = "已开启" ] && {
- if $ip6table -j TPROXY -h 2>/dev/null | grep -q '\--on-port'; then
- JUMP="TPROXY --on-port $tproxy_port --tproxy-mark $fwmark" #跳转劫持的具体命令
- [ "$lan_proxy" = true ] && start_ipt_route ip6tables mangle PREROUTING shellcrashv6_mark all
- [ "$local_proxy" = true ] && {
- if [ -n "$(grep -E '^MARK$' /proc/net/ip6_tables_targets)" ]; then
- JUMP="MARK --set-mark $fwmark" #跳转劫持的具体命令
- start_ipt_route ip6tables mangle OUTPUT shellcrashv6_mark_out all
- $ip6table -t mangle -A PREROUTING -m mark --mark $fwmark -p tcp -j TPROXY --on-port $tproxy_port
- $ip6table -t mangle -A PREROUTING -m mark --mark $fwmark -p udp -j TPROXY --on-port $tproxy_port
- else
- logger "当前设备内核可能缺少xt_mark模块支持,已放弃启动本机代理相关规则!" 31
- fi
- }
- else
- logger "当前设备内核可能缺少kmod_ipt_tproxy或者xt_mark模块支持,已放弃启动相关规则!" 31
- fi
- }
- }
- [ "$redir_mod" = "Tun模式" -o "$redir_mod" = "混合模式" -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" = "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
- start_ipt_route iptables mangle PREROUTING shellcrash_mark $protocol
- }
- [ "$local_proxy" = true ] && start_ipt_route iptables mangle OUTPUT shellcrash_mark_out $protocol
- else
- logger "当前设备内核可能缺少x_mark模块支持,已放弃启动相关规则!" 31
- fi
- [ "$ipv6_redir" = "已开启" ] && [ "$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
- start_ipt_route ip6tables mangle PREROUTING shellcrashv6_mark $protocol
- }
- [ "$local_proxy" = true ] && start_ipt_route ip6tables mangle OUTPUT shellcrashv6_mark_out $protocol
- else
- logger "当前设备内核可能缺少xt_mark模块支持,已放弃启动相关规则!" 31
- fi
- }
- }
- [ "$vm_redir" = "已开启" ] && [ -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转发
- }
- #启动DNS劫持
- [ "$dns_no" != "已禁用" -a "$dns_redir" != "已开启" -a "$firewall_area" -le 3 ] && {
- [ "$lan_proxy" = true ] && {
- start_ipt_dns iptables PREROUTING shellcrash_dns #ipv4-局域网dns转发
- if $ip6table -j REDIRECT -h 2>/dev/null | grep -q '\--to-ports'; then
- start_ipt_dns ip6tables PREROUTING shellcrashv6_dns #ipv6-局域网dns转发
- else
- $ip6table -I INPUT -p tcp --dport 53 -j REJECT >/dev/null 2>&1
- $ip6table -I INPUT -p udp --dport 53 -j REJECT >/dev/null 2>&1
- fi
- }
- [ "$local_proxy" = true ] && start_ipt_dns iptables OUTPUT shellcrash_dns_out #ipv4-本机dns转发
- }
- #屏蔽QUIC
- [ "$quic_rj" = '已启用' -a "$lan_proxy" = true -a "$redir_mod" != "Redir模式" ] && {
- [ "$dns_mod" != "fake-ip" -a "$cn_ip_route" = "已开启" ] && {
- 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" = "混合模式" ] && {
- $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模式" ] && {
- $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
- }
- }
-}
-start_nft_route() { #nftables-route通用工具
- #$1:name $2:hook(prerouting/output) $3:type(nat/mangle/filter) $4:priority(-100/-150)
- [ "$common_ports" = "已开启" ] && PORTS=$(echo $multiport | sed 's/,/, /g')
- RESERVED_IP=$(echo $reserve_ipv4 | sed 's/ /, /g')
- HOST_IP=$(echo $host_ipv4 | sed 's/ /, /g')
- [ "$1" = 'output' ] && HOST_IP="127.0.0.0/8, $(echo $local_ipv4 | sed 's/ /, /g')"
- [ "$1" = 'prerouting_vm' ] && HOST_IP="$(echo $vm_ipv4 | sed 's/ /, /g')"
- #添加新链
- nft add chain inet shellcrash $1 { type $3 hook $2 priority $4 \; }
- [ "$1" = 'prerouting_vm' ] && nft add rule inet shellcrash $1 ip saddr != {$HOST_IP} return #仅代理虚拟机流量
- #过滤dns
- nft add rule inet shellcrash $1 tcp dport 53 return
- nft add rule inet shellcrash $1 udp dport 53 return
- #防回环
- nft add rule inet shellcrash $1 meta mark $routing_mark return
- nft add rule inet shellcrash $1 meta skgid 7890 return
- [ "$firewall_area" = 5 ] && nft add rule inet shellcrash $1 ip saddr $bypass_host return
- [ -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 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 ip saddr 28.0.0.0/8 return
- nft add rule inet shellcrash $1 ip daddr {$RESERVED_IP} return #过滤保留地址
- #过滤局域网设备
- [ "$1" = 'prerouting' ] && {
- [ "$macfilter_type" != "白名单" ] && {
- [ -s "$CRASHDIR"/configs/mac ] && {
- MAC=$(awk '{printf "%s, ",$1}' "$CRASHDIR"/configs/mac)
- nft add rule inet shellcrash $1 ether saddr {$MAC} return
- }
- [ -s "$CRASHDIR"/configs/ip_filter ] && {
- FL_IP=$(awk '{printf "%s, ",$1}' "$CRASHDIR"/configs/ip_filter)
- nft add rule inet shellcrash $1 ip saddr {$FL_IP} return
- }
- nft add rule inet shellcrash $1 ip saddr != {$HOST_IP} return #仅代理本机局域网网段流量
- }
- [ "$macfilter_type" = "白名单" ] && {
- [ -s "$CRASHDIR"/configs/mac ] && MAC=$(awk '{printf "%s, ",$1}' "$CRASHDIR"/configs/mac)
- [ -s "$CRASHDIR"/configs/ip_filter ] && FL_IP=$(awk '{printf "%s, ",$1}' "$CRASHDIR"/configs/ip_filter)
- if [ -n "$MAC" ] && [ -n "$FL_IP" ]; then
- nft add rule inet shellcrash $1 ether saddr != {$MAC} ip saddr != {$FL_IP} return
- elif [ -n "$MAC" ]; then
- nft add rule inet shellcrash $1 ether saddr != {$MAC} return
- elif [ -n "$FL_IP" ]; then
- nft add rule inet shellcrash $1 ip saddr != {$FL_IP} return
- else
- nft add rule inet shellcrash $1 ip saddr != {$HOST_IP} return #仅代理本机局域网网段流量
- fi
- }
- }
- #绕过CN-IP
- [ "$dns_mod" != "fake-ip" -a "$cn_ip_route" = "已开启" -a -f "$BINDIR"/cn_ip.txt ] && {
- CN_IP=$(awk '{printf "%s, ",$1}' "$BINDIR"/cn_ip.txt)
- [ -n "$CN_IP" ] && nft add rule inet shellcrash $1 ip daddr {$CN_IP} return
- }
- #局域网ipv6支持
- if [ "$ipv6_redir" = "已开启" -a "$1" = 'prerouting' -a "$firewall_area" != 5 ]; then
- RESERVED_IP6="$(echo "$reserve_ipv6 $host_ipv6" | sed 's/ /, /g')"
- HOST_IP6="$(echo $host_ipv6 | sed 's/ /, /g')"
- #过滤保留地址及本机地址
- 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_ipv6_route" = "已开启" -a -f "$BINDIR"/cn_ipv6.txt ] && {
- CN_IP6=$(awk '{printf "%s, ",$1}' "$BINDIR"/cn_ipv6.txt)
- [ -n "$CN_IP6" ] && nft add rule inet shellcrash $1 ip6 daddr {$CN_IP6} return
- }
- elif [ "$ipv6_redir" = "已开启" -a "$1" = 'output' -a \( "$firewall_area" = 2 -o "$firewall_area" = 3 \) ]; then
- RESERVED_IP6="$(echo "$reserve_ipv6 $host_ipv6" | sed 's/ /, /g')"
- HOST_IP6="::1, $(echo $host_ipv6 | sed 's/ /, /g')"
- #过滤保留地址及本机地址
- 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_ipv6_route" = "已开启" -a -f "$BINDIR"/cn_ipv6.txt ] && {
- CN_IP6=$(awk '{printf "%s, ",$1}' "$BINDIR"/cn_ipv6.txt)
- [ -n "$CN_IP6" ] && nft add rule inet shellcrash $1 ip6 daddr {$CN_IP6} return
- }
- else
- nft add rule inet shellcrash $1 meta nfproto ipv6 return
- fi
- #添加通用路由
- nft add rule inet shellcrash "$1" "$JUMP"
- #处理特殊路由
- [ "$redir_mod" = "混合模式" ] && {
- 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
- }
- #nft add rule inet shellcrash local_tproxy log prefix \"pre\" level debug
-}
-start_nft_dns() { #nftables-dns
- HOST_IP=$(echo $host_ipv4 | sed 's/ /, /g')
- HOST_IP6=$(echo $host_ipv6 | sed 's/ /, /g')
- [ "$1" = 'output' ] && HOST_IP="127.0.0.0/8, $(echo $local_ipv4 | sed 's/ /, /g')"
- [ "$1" = 'prerouting_vm' ] && HOST_IP="$(echo $vm_ipv4 | sed 's/ /, /g')"
- nft add chain inet shellcrash "$1"_dns { type nat hook $2 priority -100 \; }
- #过滤非dns请求
- nft add rule inet shellcrash "$1"_dns udp dport != 53 return
- nft add rule inet shellcrash "$1"_dns tcp dport != 53 return
- #防回环
- nft add rule inet shellcrash "$1"_dns meta mark $routing_mark return
- nft add rule inet shellcrash "$1"_dns meta skgid { 453, 7890 } return
- [ "$firewall_area" = 5 ] && nft add rule inet shellcrash "$1"_dns ip saddr $bypass_host return
- nft add rule inet shellcrash "$1"_dns ip saddr != {$HOST_IP} return #屏蔽外部请求
- [ "$1" = 'prerouting' ] && nft add rule inet shellcrash "$1"_dns ip6 saddr != {$HOST_IP6} return #屏蔽外部请求
- #过滤局域网设备
- [ "$1" = 'prerouting' ] && [ -s "$CRASHDIR"/configs/mac ] && {
- MAC=$(awk '{printf "%s, ",$1}' "$CRASHDIR"/configs/mac)
- if [ "$macfilter_type" = "黑名单" ]; then
- nft add rule inet shellcrash "$1"_dns ether saddr {$MAC} return
- else
- nft add rule inet shellcrash "$1"_dns ether saddr != {$MAC} return
- fi
- }
- nft add rule inet shellcrash "$1"_dns udp dport 53 redirect to ${dns_port}
- nft add rule inet shellcrash "$1"_dns tcp dport 53 redirect to ${dns_port}
-}
-start_nft_wan() { #nftables公网防火墙
- #获取局域网host地址
- getlanip
- HOST_IP=$(echo $host_ipv4 | sed 's/ /, /g')
- nft add chain inet shellcrash input { type filter hook input priority -100 \; }
- nft add rule inet shellcrash input ip daddr 127.0.0.1 accept
- if [ "$public_support" = "已开启" ]; then
- nft add rule inet shellcrash input tcp dport $db_port accept
- else
- #仅允许非公网设备访问面板
- nft add rule inet shellcrash input tcp dport $db_port ip saddr {$HOST_IP} accept
- nft add rule inet shellcrash input tcp dport $db_port reject
- fi
- if [ "$public_mixport" = "已开启" ]; then
- nft add rule inet shellcrash input tcp dport $mix_port accept
- else
- #仅允许局域网设备访问混合端口
- nft add rule inet shellcrash input tcp dport $mix_port ip saddr {$HOST_IP} accept
- nft add rule inet shellcrash input tcp dport $mix_port reject
- fi
-}
-start_nftables() { #nftables配置总入口
- #初始化nftables
- nft add table inet shellcrash 2>/dev/null
- nft flush table inet shellcrash 2>/dev/null
- #公网访问防火墙
- [ "$systype" != 'container' ] && start_nft_wan
- #启动DNS劫持
- [ "$dns_no" != "已禁用" -a "$dns_redir" != "已开启" -a "$firewall_area" -le 3 ] && {
- [ "$lan_proxy" = true ] && start_nft_dns prerouting prerouting #局域网dns转发
- [ "$local_proxy" = true ] && start_nft_dns output output #本机dns转发
- }
- #分模式设置流量劫持
- [ "$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) && {
- 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 ] && {
- JUMP="meta l4proto {tcp, udp} mark set $fwmark" #跳转劫持的具体命令
- start_nft_route output output route -150
- nft add chain inet shellcrash mark_out { type filter hook prerouting priority -100 \; }
- nft add rule inet shellcrash mark_out meta mark $fwmark meta l4proto {tcp, udp} tproxy to :$tproxy_port
- }
- }
- [ "$tun_statu" = true ] && {
- [ "$redir_mod" = "Tun模式" ] && JUMP="meta l4proto {tcp, udp} mark set $fwmark" #跳转劫持的具体命令
- [ "$redir_mod" = "混合模式" ] && JUMP="meta l4proto udp mark set $fwmark" #跳转劫持的具体命令
- [ "$lan_proxy" = true ] && {
- start_nft_route prerouting prerouting filter -150
- #放行流量
- nft list table inet fw4 >/dev/null 2>&1 || nft add table inet fw4
- nft list chain inet fw4 forward >/dev/null 2>&1 || nft add chain inet fw4 forward { type filter hook forward priority filter \; } 2>/dev/null
- nft list chain inet fw4 input >/dev/null 2>&1 || nft add chain inet fw4 input { type filter hook input priority filter \; } 2>/dev/null
- nft list chain inet fw4 forward | grep -q 'oifname "utun" accept' || nft insert rule inet fw4 forward oifname "utun" accept
- nft list chain inet fw4 input | grep -q 'iifname "utun" accept' || nft insert rule inet fw4 input iifname "utun" accept
- }
- [ "$local_proxy" = true ] && start_nft_route output output route -150
- }
- [ "$firewall_area" = 5 ] && {
- [ "$redir_mod" = "T&U旁路转发" ] && JUMP="meta l4proto {tcp, udp} mark set $fwmark" #跳转劫持的具体命令
- [ "$redir_mod" = "TCP旁路转发" ] && JUMP="meta l4proto tcp mark set $fwmark" #跳转劫持的具体命令
- [ "$lan_proxy" = true ] && start_nft_route prerouting prerouting filter -150
- [ "$local_proxy" = true ] && start_nft_route output output route -150
- }
- [ "$vm_redir" = "已开启" ] && [ -n "$$vm_ipv4" ] && {
- start_nft_dns prerouting_vm prerouting
- JUMP="meta l4proto tcp redirect to $redir_port" #跳转劫持的具体命令
- start_nft_route prerouting_vm prerouting nat -100
- }
- #屏蔽QUIC
- [ "$quic_rj" = '已启用' -a "$lan_proxy" = true ] && {
- [ "$redir_mod" = "Tproxy模式" ] && {
- nft add chain inet shellcrash quic_rj { type filter hook input priority 0 \; }
- [ -n "$CN_IP" ] && nft add rule inet shellcrash quic_rj ip daddr {$CN_IP} return
- [ -n "$CN_IP6" ] && nft add rule inet shellcrash quic_rj ip6 daddr {$CN_IP6} return
- nft add rule inet shellcrash quic_rj udp dport {443, 8443} reject comment 'ShellCrash-QUIC-REJECT'
- }
- [ "$redir_mod" = "Tun模式" -o "$redir_mod" = "混合模式" ] && {
- nft insert rule inet fw4 forward oifname "utun" udp dport {443, 8443} reject comment 'ShellCrash-QUIC-REJECT'
- [ -n "$CN_IP" ] && nft insert rule inet fw4 forward oifname "utun" ip daddr {$CN_IP} return
- [ -n "$CN_IP6" ] && nft insert rule inet fw4 forward oifname "utun" ip6 daddr {$CN_IP6} return
- }
- }
-}
-start_firewall() { #路由规则总入口
- getlanip #获取局域网host地址
- #设置策略路由
- [ "$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
- }
- #添加ipv6路由
- [ "$ipv6_redir" = "已开启" -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
- }
- #判断代理用途
- [ "$firewall_area" = 2 -o "$firewall_area" = 3 ] && local_proxy=true
- [ "$firewall_area" = 1 -o "$firewall_area" = 3 -o "$firewall_area" = 5 ] && lan_proxy=true
- #防火墙配置
- [ "$firewall_mod" = 'iptables' ] && start_iptables
- [ "$firewall_mod" = 'nftables' ] && 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
- }
- #openwrt使用dnsmasq转发DNS
- if [ "$dns_redir" = "已开启" -a "$firewall_area" -le 3 -a "$dns_no" != "已禁用" ]; then
- uci del dhcp.@dnsmasq[-1].server >/dev/null 2>&1
- uci delete dhcp.@dnsmasq[0].resolvfile 2>/dev/null
- uci add_list dhcp.@dnsmasq[0].server=127.0.0.1#$dns_port >/dev/null 2>&1
- uci set dhcp.@dnsmasq[0].noresolv=1 2>/dev/null
- uci commit dhcp >/dev/null 2>&1
- /etc/init.d/dnsmasq restart >/dev/null 2>&1
- elif [ "$(uci get dhcp.@dnsmasq[0].dns_redirect 2>/dev/null)" = 1 ]; then
- uci del dhcp.@dnsmasq[0].dns_redirect
- uci commit dhcp.@dnsmasq[0]
- fi
-}
-stop_firewall() { #还原防火墙配置
- #获取局域网host地址
- getlanip
- #重置iptables相关规则
- ckcmd 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" -a "$cn_ip_route" = "已开启" ] && 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
- #公网访问
- for ip in $host_ipv4 $local_ipv4 $reserve_ipv4; do
- $iptable -D INPUT -p tcp -s $ip --dport $mix_port -j ACCEPT 2>/dev/null
- $iptable -D INPUT -p tcp -s $ip --dport $db_port -j ACCEPT 2>/dev/null
- done
- $iptable -D INPUT -p tcp -d 127.0.0.1 -j ACCEPT 2>/dev/null
- $iptable -D INPUT -p tcp --dport $mix_port -j REJECT 2>/dev/null
- $iptable -D INPUT -p tcp --dport $mix_port -j ACCEPT 2>/dev/null
- $iptable -D INPUT -p tcp --dport $db_port -j REJECT 2>/dev/null
- $iptable -D INPUT -p tcp --dport $db_port -j ACCEPT 2>/dev/null
- #清理shellcrash自建表
- for words in shellcrash_dns shellcrash shellcrash_out shellcrash_dns_out shellcrash_vm shellcrash_vm_dns; do
- $iptable -t nat -F $words 2>/dev/null
- $iptable -t nat -X $words 2>/dev/null
- done
- for words in shellcrash_mark shellcrash_mark_out; do
- $iptable -t mangle -F $words 2>/dev/null
- $iptable -t mangle -X $words 2>/dev/null
- done
- }
- #重置ipv6规则
- ckcmd 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" -a "$cn_ipv6_route" = "已开启" ] && 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 -p tcp --dport $mix_port -j REJECT 2>/dev/null
- $ip6table -D INPUT -p tcp --dport $mix_port -j ACCEPT 2>/dev/null
- $ip6table -D INPUT -p tcp --dport $db_port -j REJECT 2>/dev/null
- $ip6table -D INPUT -p tcp --dport $db_port -j ACCEPT 2>/dev/null
- #清理shellcrash自建表
- for words in shellcrashv6_dns shellcrashv6 shellcrashv6_out; do
- $ip6table -t nat -F $words 2>/dev/null
- $ip6table -t nat -X $words 2>/dev/null
- done
- for words in shellcrashv6_mark shellcrashv6_mark_out; do
- $ip6table -t mangle -F $words 2>/dev/null
- $ip6table -t mangle -X $words 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
- ipset destroy cn_ip6 >/dev/null 2>&1
- #移除dnsmasq转发规则
- [ "$dns_redir" = "已开启" ] && {
- uci del dhcp.@dnsmasq[-1].server >/dev/null 2>&1
- uci set dhcp.@dnsmasq[0].noresolv=0 2>/dev/null
- uci commit dhcp >/dev/null 2>&1
- /etc/init.d/dnsmasq restart >/dev/null 2>&1
- }
- #清理路由规则
- ip rule del fwmark $fwmark table $table 2>/dev/null
- ip route flush table $table 2>/dev/null
- ip -6 rule del fwmark $fwmark table $((table + 1)) 2>/dev/null
- ip -6 route flush table $((table + 1)) 2>/dev/null
- #重置nftables相关规则
- ckcmd nft && {
- nft flush table inet shellcrash >/dev/null 2>&1
- nft delete table inet shellcrash >/dev/null 2>&1
- }
- #还原防火墙文件
- [ -s /etc/init.d/firewall.bak ] && mv -f /etc/init.d/firewall.bak /etc/init.d/firewall
- #others
- [ "$systype" != 'container' ] && sed -i '/shellcrash-dns-repair/d' /etc/resolv.conf >/dev/null 2>&1
-}
-#启动相关
-web_save() { #最小化保存面板节点选择
- #使用get_save获取面板节点设置
- 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"' | grep -aoE '"name":.*"now":".*",' >"$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
- #获取面板设置
- #[ "$crashcore" != singbox ] && get_save http://127.0.0.1:${db_port}/configs > "$TMPDIR"/web_configs
- #对比文件,如果有变动且不为空则写入磁盘,否则清除缓存
- for file in web_save web_configs; do
- if [ -s "$TMPDIR"/${file} ]; then
- compare "$TMPDIR"/${file} "$CRASHDIR"/configs/${file}
- [ "$?" = 0 ] && rm -rf "$TMPDIR"/${file} || mv -f "$TMPDIR"/${file} "$CRASHDIR"/configs/${file}
- fi
- done
-}
-web_restore() { #还原面板选择
- #设置循环检测面板端口以判定服务启动是否成功
- test=""
- i=1
- while [ -z "$test" -a "$i" -lt 30 ]; do
- test=$(get_save http://127.0.0.1:${db_port}/proxies | grep -o proxies)
- i=$((i + 1))
- sleep 2
- done
- [ -n "$test" ] && {
- #发送节点选择数据
- [ -s "$CRASHDIR"/configs/web_save ] && {
- 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
- }
- #还原面板设置
- #[ "$crashcore" != singbox ] && [ -s "$CRASHDIR"/configs/web_configs ] && {
- #sleep 5
- #put_save http://127.0.0.1:${db_port}/configs "$(cat "$CRASHDIR"/configs/web_configs)" PATCH
- #}
- }
-}
-makehtml() { #生成面板跳转文件
- cat >"$BINDIR"/ui/index.html <
-
-
-
-
-
-
-
- ShellCrash面板提示
-
-
-
-
您还未安装本地面板
-
请在脚本更新功能中(9-4)安装
或者使用在线面板:
-
-
-&1 | grep \"address\" | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
- [ -z "$host_pac" ] && host_pac=$(ip a 2>&1 | grep -w 'inet' | grep 'global' | grep -E ' 1(92|0|72)\.' | sed 's/.*inet.//g' | sed 's/\/[0-9][0-9].*$//g' | head -n 1)
- cat >"$TMPDIR"/shellcrash_pac <&1 | grep -o 'no-same-owner')" ] && tar_para='--no-same-owner' #tar命令兼容
- [ -n "$(find --help 2>&1 | grep -o size)" ] && find_para=' -size +2000' #find命令兼容
- tar_core() {
- 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
- }
- [ -z "$(find "$TMPDIR"/CrashCore $find_para 2>/dev/null)" ] && [ -n "$(find "$BINDIR"/CrashCore $find_para 2>/dev/null)" ] && mv "$BINDIR"/CrashCore "$TMPDIR"/CrashCore
- [ -z "$(find "$TMPDIR"/CrashCore $find_para 2>/dev/null)" ] && [ -n "$(find "$BINDIR"/CrashCore.tar.gz $find_para 2>/dev/null)" ] &&
- tar_core "$BINDIR"/CrashCore.tar.gz CrashCore
- [ -z "$(find "$TMPDIR"/CrashCore $find_para 2>/dev/null)" ] && {
- logger "未找到【$crashcore】核心,正在下载!" 33
- [ -z "$cpucore" ] && . "$CRASHDIR"/webget.sh && getcpucore
- [ -z "$cpucore" ] && logger 找不到设备的CPU信息,请手动指定处理器架构类型! 31 && exit 1
- get_bin "$TMPDIR"/CrashCore.tar.gz "bin/$crashcore/${target}-linux-${cpucore}.tar.gz"
- #校验内核
- tar_core "$TMPDIR"/CrashCore.tar.gz core_new
- chmod +x "$TMPDIR"/core_new
- if echo "$crashcore" | grep -q 'singbox'; then
- core_v=$("$TMPDIR"/core_new version 2>/dev/null | grep version | awk '{print $3}')
- COMMAND='"$TMPDIR/CrashCore run -D $BINDIR -C $TMPDIR/jsons"'
- else
- core_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 "$core_v" ]; then
- rm -rf "$TMPDIR"/CrashCore
- logger "核心下载失败,请重新运行或更换安装源!" 31
- exit 1
- else
- mv -f "$TMPDIR"/core_new "$TMPDIR"/CrashCore
- mv -f "$TMPDIR"/CrashCore.tar.gz "$BINDIR"/CrashCore.tar.gz
- setconfig COMMAND "$COMMAND" "$CRASHDIR"/configs/command.env && . "$CRASHDIR"/configs/command.env
- setconfig crashcore $crashcore
- setconfig core_v $core_v
- fi
- }
- [ ! -x "$TMPDIR"/CrashCore ] && chmod +x "$TMPDIR"/CrashCore 2>/dev/null #自动授权
- [ "$start_old" != "已开启" -a "$(cat /proc/1/comm)" = "systemd" ] && restorecon -RF $CRASHDIR 2>/dev/null #修复SELinux权限问题
- return 0
-}
-core_exchange() { #升级为高级内核
- #$1:目标内核 $2:提示语句
- logger "检测到${2}!将改为使用${1}核心启动!" 33
- rm -rf "$TMPDIR"/CrashCore
- rm -rf "$BINDIR"/CrashCore
- rm -rf "$BINDIR"/CrashCore.tar.gz
- crashcore="$1"
- setconfig crashcore "$1"
- echo "-----------------------------------------------"
-}
-clash_check() { #clash启动前检查
- #检测vless/hysteria协议
- [ "$crashcore" != "meta" ] && [ -n "$(cat $core_config | grep -oE 'type: vless|type: hysteria')" ] && core_exchange meta 'vless/hy协议'
- #检测是否存在高级版规则或者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 '当前内核不支持的配置'
- fi
- [ "$crashcore" = "clash" ] && [ "$firewall_area" = 2 -o "$firewall_area" = 3 ] && [ -z "$(grep '0:7890' /etc/passwd)" ] &&
- core_exchange meta '当前内核不支持非root用户启用本机代理'
- core_check
- #预下载GeoIP数据库并排除存在自定义数据库链接的情况
- [ -n "$(grep -oEi 'geoip:' "$CRASHDIR"/yamls/*.yaml)" ] && [ -z "$(grep -oEi 'geoip:|mmdb:' "$CRASHDIR"/yamls/*.yaml)" ] && ckgeo Country.mmdb cn_mini.mmdb
- #预下载GeoSite数据库并排除存在自定义数据库链接的情况
- [ -n "$(grep -oEi 'geosite:' "$CRASHDIR"/yamls/*.yaml)" ] && [ -z "$(grep -oEi 'geosite:' "$CRASHDIR"/yamls/*.yaml)" ] && ckgeo GeoSite.dat geosite.dat
- #预下载cn.mrs数据库
- [ "$dns_mod" = "mix" ] || [ "$dns_mod" = "route" ] && ! grep -Eq '^[[:space:]]*cn:' "$CRASHDIR"/yamls/*.yaml && ckgeo ruleset/cn.mrs mrs_geosite_cn.mrs
- return 0
-}
-singbox_check() { #singbox启动前检查
- #检测singboxr专属功能
- [ "$crashcore" != "singboxr" ] && [ -n "$(cat "$CRASHDIR"/jsons/*.json | grep -oE '"shadowsocksr"|"providers"')" ] && core_exchange singboxr 'singboxr内核专属功能'
- core_check
- #预下载cn.srs数据库
- [ "$dns_mod" = "mix" ] || [ "$dns_mod" = "route" ] && ! grep -Eq '"tag" *:[[:space:]]*"cn"' "$CRASHDIR"/jsons/*.json && ckgeo ruleset/cn.srs srs_geosite_cn.srs
- return 0
-}
-network_check() { #检查是否联网
- for text in 223.5.5.5 dns.alidns.com doh.pub doh.360.cn; do
- ping -c 3 $text >/dev/null 2>&1 && return 0
- sleep 5
- done
- logger "当前设备无法连接网络,已停止启动!" 33
- exit 1
-}
-bfstart() { #启动前
- routing_mark=$((fwmark + 2))
- #检测网络连接
- [ "$network_check" != "已禁用" ] && [ ! -f "$TMPDIR"/crash_start_time ] && ckcmd ping && network_check
- [ ! -d "$BINDIR"/ui ] && mkdir -p "$BINDIR"/ui
- [ -z "$crashcore" ] && crashcore=meta
- #执行条件任务
- [ -s "$CRASHDIR"/task/bfstart ] && . "$CRASHDIR"/task/bfstart
- #检查内核配置文件
- if [ ! -f $core_config ]; then
- if [ -n "$Url" -o -n "$Https" ]; then
- logger "未找到配置文件,正在下载!" 33
- get_core_config
- else
- logger "未找到配置文件链接,请先导入配置文件!" 31
- exit 1
- fi
- fi
- #检查dashboard文件
- if [ -f "$CRASHDIR"/ui/CNAME -a ! -f "$BINDIR"/ui/CNAME ]; then
- cp -rf "$CRASHDIR"/ui "$BINDIR"
- fi
- [ ! -s "$BINDIR"/ui/index.html ] && makehtml #如没有面板则创建跳转界面
- catpac #生成pac文件
- #内核及内核配置文件检查
- if echo "$crashcore" | grep -q 'singbox'; then
- singbox_check
- [ -d "$TMPDIR"/jsons ] && rm -rf "$TMPDIR"/jsons/* || mkdir -p "$TMPDIR"/jsons #准备目录
- [ "$disoverride" != "1" ] && modify_json || ln -sf $core_config "$TMPDIR"/jsons/config.json
- else
- clash_check
- [ "$disoverride" != "1" ] && modify_yaml || ln -sf $core_config "$TMPDIR"/config.yaml
- fi
- #检查下载cnip绕过相关文件
- [ "$firewall_mod" = nftables ] || ckcmd ipset && [ "$dns_mod" != "fake-ip" ] && {
- [ "$cn_ip_route" = "已开启" ] && cn_ip_route
- [ "$ipv6_redir" = "已开启" ] && [ "$cn_ipv6_route" = "已开启" ] && cn_ipv6_route
- }
- #添加shellcrash用户
- [ "$firewall_area" = 2 ] || [ "$firewall_area" = 3 ] || [ "$(cat /proc/1/comm)" = "systemd" ] &&
- [ -z "$(id shellcrash 2>/dev/null | grep 'root')" ] && {
- ckcmd userdel && userdel shellcrash 2>/dev/null
- sed -i '/0:7890/d' /etc/passwd
- sed -i '/x:7890/d' /etc/group
- if ckcmd useradd; then
- useradd shellcrash -u 7890
- sed -Ei s/7890:7890/0:7890/g /etc/passwd
- else
- echo "shellcrash:x:0:7890:::" >>/etc/passwd
- fi
- }
- #清理debug日志
- rm -rf "$TMPDIR"/debug.log
- rm -rf "$CRASHDIR"/debug.log
- return 0
-}
-afstart() { #启动后
- [ -z "$firewall_area" ] && firewall_area=1
- #延迟启动
- [ ! -f "$TMPDIR"/crash_start_time ] && [ -n "$start_delay" ] && [ "$start_delay" -gt 0 ] && {
- logger "ShellCrash将延迟$start_delay秒启动" 31
- sleep $start_delay
- }
- #设置循环检测面板端口以判定服务启动是否成功
- i=1
- while [ -z "$test" -a "$i" -lt 30 ]; do
- echo "$i" | grep -q '10' && echo -ne "服务正在启动,请耐心等待!\r"
- sleep 1
- if curl --version >/dev/null 2>&1; then
- test=$(curl -s -H "Authorization: Bearer $secret" http://127.0.0.1:${db_port}/configs | grep -o port)
- else
- test=$(wget -q --header="Authorization: Bearer $secret" -O - http://127.0.0.1:${db_port}/configs | grep -o port)
- fi
- i=$((i + 1))
- done
- if [ -n "$test" -o -n "$(pidof CrashCore)" ]; then
- [ "$start_old" = "已开启" ] && rm -rf "$TMPDIR"/CrashCore #删除缓存目录内核文件
- start_firewall #配置防火墙流量劫持
- mark_time #标记启动时间
- [ -s "$CRASHDIR"/configs/web_save ] && web_restore >/dev/null 2>&1 & #后台还原面板配置
- {
- sleep 5
- logger ShellCrash服务已启动!
- } & #推送日志
- ckcmd mtd_storage.sh && mtd_storage.sh save >/dev/null 2>&1 & #Padavan保存/etc/storage
- #加载定时任务
- [ -s "$CRASHDIR"/task/cron ] && croncmd "$CRASHDIR"/task/cron
- [ -s "$CRASHDIR"/task/running ] && {
- cronset '运行时每'
- while read line; do
- cronset '2fjdi124dd12s' "$line"
- done <"$CRASHDIR"/task/running
- }
- [ "$start_old" = "已开启" ] && cronset '保守模式守护进程' "* * * * * test -z \"\$(pidof CrashCore)\" && "$CRASHDIR"/start.sh daemon #ShellCrash保守模式守护进程"
- #加载条件任务
- [ -s "$CRASHDIR"/task/afstart ] && { . "$CRASHDIR"/task/afstart; } &
- [ -s "$CRASHDIR"/task/affirewall -a -s /etc/init.d/firewall -a ! -f /etc/init.d/firewall.bak ] && {
- #注入防火墙
- line=$(grep -En "fw.* restart" /etc/init.d/firewall | cut -d ":" -f 1)
- sed -i.bak "${line}a\\. "$CRASHDIR"/task/affirewall" /etc/init.d/firewall
- line=$(grep -En "fw.* start" /etc/init.d/firewall | cut -d ":" -f 1)
- sed -i "${line}a\\. "$CRASHDIR"/task/affirewall" /etc/init.d/firewall
- } &
- else
- start_error
- $0 stop
- fi
-}
-start_error() { #启动报错
- if [ "$start_old" != "已开启" ] && ckcmd journalctl; then
- 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
- fi
- error=$(cat $TMPDIR/core_test.log | grep -iEo 'error.*=.*|.*ERROR.*|.*FATAL.*')
- logger "服务启动失败!请查看报错信息!详细信息请查看$TMPDIR/core_test.log" 33
- logger "$error" 31
- exit 1
-}
-start_old() { #保守模式
- #使用传统后台执行二进制文件的方式执行
- if ckcmd su && [ -n "$(grep 'shellcrash:x:0:7890' /etc/passwd)" ]; then
- su shellcrash -c "$COMMAND >/dev/null 2>&1" &
- else
- ckcmd nohup && local nohup=nohup
- $nohup $COMMAND >/dev/null 2>&1 &
- fi
- afstart &
-}
-#杂项
-update_config() { #更新订阅并重启
- get_core_config &&
- $0 restart
-}
-hotupdate() { #热更新订阅
- get_core_config
- core_check
- modify_$format &&
- put_save http://127.0.0.1:${db_port}/configs "{\"path\":\""$CRASHDIR"/config.$format\"}"
- rm -rf "$TMPDIR"/CrashCore
-}
-
-getconfig #读取配置及全局变量
case "$1" in
@@ -2050,18 +39,18 @@ start)
stop_firewall #清理路由策略
#使用不同方式启动服务
if [ "$firewall_area" = "5" ]; then #主旁转发
- start_firewall
- elif [ "$start_old" = "已开启" ]; then
- bfstart && start_old
- elif [ -f /etc/rc.common -a "$(cat /proc/1/comm)" = "procd" ]; 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" -a "$(cat /proc/1/comm)" = "systemd" ]; then
- bfstart && {
- FragmentPath=$(systemctl show -p FragmentPath shellcrash | sed 's/FragmentPath=//')
- [ -f $FragmentPath ] && setconfig ExecStart "$COMMAND >/dev/null" "$FragmentPath"
- systemctl daemon-reload
- systemctl start shellcrash.service || start_error
- }
+ elif [ "$USER" = "root" ] && grep -q 'systemd' /proc/1/comm; then
+ FragmentPath=$(systemctl show -p FragmentPath shellcrash | sed 's/FragmentPath=//')
+ [ -f $FragmentPath ] && {
+ setconfig 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
@@ -2071,7 +60,7 @@ start)
rc-service shellcrash stop >/dev/null 2>&1
rc-service shellcrash start
else
- bfstart && start_old
+ start_l
fi
;;
stop)
@@ -2082,10 +71,12 @@ stop)
cronset '运行时每'
cronset '流媒体预解析'
#多种方式结束进程
-
- if [ "$start_old" != "已开启" -a "$USER" = "root" -a "$(cat /proc/1/comm)" = "systemd" ]; then
+ if [ -f "$TMPDIR/shellcrash.pid" ];then
+ kill -TERM "$(cat "$TMPDIR/shellcrash.pid")"
+ rm -f "$TMPDIR/shellcrash.pid"
+ elif [ "$USER" = "root" ] && grep -q 'systemd' /proc/1/comm; then
systemctl stop shellcrash.service >/dev/null 2>&1
- elif [ -f /etc/rc.common -a "$(cat /proc/1/comm)" = "procd" ]; then
+ 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
@@ -2095,7 +86,7 @@ stop)
else
stop_firewall #清理路由策略
fi
- PID=$(pidof CrashCore) && [ -n "$PID" ] && kill -9 $PID >/dev/null 2>&1
+ PID=$(pidof CrashCore) && [ -n "$PID" ] && ckcmd killall && killall CrashCore 2>/dev/null
#清理缓存目录
rm -rf "$TMPDIR"/CrashCore
;;
@@ -2103,6 +94,9 @@ restart)
$0 stop
$0 start
;;
+init)
+ . "$CRASHDIR"/starts/general_init.sh
+ ;;
daemon)
if [ -f $TMPDIR/crash_start_time ]; then
$0 start
@@ -2129,78 +123,6 @@ debug)
fi
afstart
;;
-init)
- 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 /etc/profile ] && profile=/etc/profile || profile=/etc_ro/profile
- mount -t tmpfs -o remount,rw,size=45M tmpfs /tmp #增加/tmp空间以适配新的内核压缩方式
- sed -i '' $profile #将软链接转化为一般文件
- elif [ -d "/jffs" ]; then
- sleep 60
- if [ -w /etc/profile ]; then
- profile=/etc/profile
- else
- profile=$(cat /etc/profile | grep -oE '\-f.*jffs.*profile' | awk '{print $2}')
- fi
- fi
- [ -z "$my_alias" ] && my_alias=crash
- sed -i "/ShellCrash\/menu.sh/"d "$profile"
- echo "alias ${my_alias}=\"sh $CRASHDIR/menu.sh\"" >>"$profile"
- sed -i "/export CRASHDIR/d" "$profile"
- echo "export CRASHDIR=\"$CRASHDIR\"" >>"$profile"
- [ -f "$CRASHDIR"/.dis_startup ] && cronset "保守模式守护进程" || $0 start
- ;;
-webget)
- #设置临时代理
- if pidof CrashCore >/dev/null; then
- [ -n "$authentication" ] && auth="$authentication@" || auth=""
- export all_proxy="http://${auth}127.0.0.1:$mix_port"
- url=$(printf '%s\n' "$3" |
- 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' "$3" |
- sed 's#https://raw.githubusercontent.com/juewuy/ShellCrash/#https://testingcf.jsdelivr.net/gh/juewuy/ShellCrash@#')
- fi
- #参数【$2】代表下载目录,【$3】代表在线地址
- #参数【$4】代表输出显示,【$5】不启用重定向
- #参数【$6】代表验证证书,【$7】使用自定义UA
- [ -n "$7" ] && agent="--user-agent \"$7\""
- if wget --help 2>&1 | grep -q 'show-progress' >/dev/null 2>&1; then
- [ "$4" = "echooff" ] && progress='-q' || progress='-q --show-progress'
- [ "$5" = "rediroff" ] && redirect='--max-redirect=0' || redirect=''
- [ "$6" = "skipceroff" ] && certificate='' || certificate='--no-check-certificate'
- wget -Y on $agent $progress $redirect $certificate --timeout=3 -O "$2" "$url" && exit 0 #成功则退出否则重试
- wget -Y off $agent $progress $redirect $certificate --timeout=5 -O "$2" "$3"
- exit $?
- elif curl --version >/dev/null 2>&1; then
- [ "$4" = "echooff" ] && progress='-s' || progress='-#'
- [ "$5" = "rediroff" ] && redirect='' || redirect='-L'
- [ "$6" = "skipceroff" ] && certificate='' || certificate='-k'
- if curl --version | grep -q '^curl 8.' && ckcmd base64; then
- auth_b64=$(printf '%s' "$authentication" | base64)
- result=$(curl $agent -w '%{http_code}' --connect-timeout 3 --proxy-header "Proxy-Authorization: Basic $auth_b64" $progress $redirect $certificate -o "$2" "$url")
- else
- result=$(curl $agent -w '%{http_code}' --connect-timeout 3 $progress $redirect $certificate -o "$2" "$url")
- fi
- [ "$result" = "200" ] && exit 0 #成功则退出否则重试
- export all_proxy=""
- result=$(curl $agent -w '%{http_code}' --connect-timeout 5 $progress $redirect $certificate -o "$2" "$3")
- [ "$result" = "200" ]
- exit $?
- elif ckcmd wget;then
- [ "$4" = "echooff" ] && progress='-q'
- wget -Y on $progress -O "$2" "$url" && exit 0 #成功则退出否则重试
- wget -Y off $progress -O "$2" "$3"
- exit $?
- else
- echo "找不到可用下载工具!!!请安装Curl或Wget!!!"
- exit 1
- fi
- ;;
*)
"$1" "$2" "$3" "$4" "$5" "$6" "$7"
;;
diff --git a/scripts/starts/README.md b/scripts/starts/README.md
new file mode 100644
index 00000000..b7e2b4d6
--- /dev/null
+++ b/scripts/starts/README.md
@@ -0,0 +1,3 @@
+用于存放负责启动和服务相关的脚本
+
+此处脚本内容不应包含任何具体中文说明,log内容的文字应当从相关lang文件调用
\ No newline at end of file
diff --git a/scripts/starts/afstart.sh b/scripts/starts/afstart.sh
new file mode 100644
index 00000000..675c0f3b
--- /dev/null
+++ b/scripts/starts/afstart.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+#初始化目录
+[ -z "$CRASHDIR" ] && CRASHDIR=$( cd $(dirname $0);cd ..;pwd)
+. "$CRASHDIR"/libs/get_config.sh
+#加载工具
+. "$CRASHDIR"/libs/check_cmd.sh
+. "$CRASHDIR"/libs/logger.sh
+. "$CRASHDIR"/libs/set_cron.sh
+#缺省值
+[ -z "$firewall_area" ] && firewall_area=1
+#延迟启动
+[ ! -f "$TMPDIR"/crash_start_time ] && [ -n "$start_delay" ] && [ "$start_delay" -gt 0 ] && {
+ logger "ShellCrash将延迟$start_delay秒启动" 31
+ sleep "$start_delay"
+}
+#设置循环检测面板端口以判定服务启动是否成功
+. "$CRASHDIR"/libs/start_wait.sh
+if [ -n "$test" -o -n "$(pidof CrashCore)" ]; then
+ [ "$start_old" = "ON" ] && [ ! -L "$TMPDIR"/CrashCore ] && rm -f "$TMPDIR"/CrashCore #删除缓存目录内核文件
+ . "$CRASHDIR"/starts/fw_start.sh #配置防火墙流量劫持
+ date +%s >"$TMPDIR"/crash_start_time #标记启动时间
+ #TG机器人守护进程
+ [ "$bot_tg_service" = ON ] && . "$CRASHDIR"/menus/bot_tg_service.sh && bot_tg_cron
+ #后台还原面板配置
+ [ -s "$CRASHDIR"/configs/web_save ] && {
+ . "$CRASHDIR"/libs/web_restore.sh
+ web_restore >/dev/null 2>&1 &
+ }
+ #推送日志
+ {
+ sleep 5
+ logger ShellCrash服务已启动!
+ } &
+ ckcmd mtd_storage.sh && mtd_storage.sh save >/dev/null 2>&1 & #Padavan保存/etc/storage
+ #加载定时任务
+ [ -s "$CRASHDIR"/task/cron ] && croncmd "$CRASHDIR"/task/cron
+ [ -s "$CRASHDIR"/task/running ] && {
+ cronset '运行时每'
+ while read line; do
+ cronset '2fjdi124dd12s' "$line"
+ done <"$CRASHDIR"/task/running
+ }
+ [ "$start_old" = "ON" ] && cronset '保守模式守护进程' "* * * * * /bin/sh $CRASHDIR/starts/start_legacy_wd.sh shellcrash #ShellCrash保守模式守护进程"
+ #加载条件任务
+ [ -s "$CRASHDIR"/task/afstart ] && { . "$CRASHDIR"/task/afstart; } &
+ [ -s "$CRASHDIR"/task/affirewall -a -s /etc/init.d/firewall -a ! -f /etc/init.d/firewall.bak ] && {
+ #注入防火墙
+ line=$(grep -En "fw.* restart" /etc/init.d/firewall | cut -d ":" -f 1)
+ sed -i.bak "${line}a\\. "$CRASHDIR"/task/affirewall" /etc/init.d/firewall
+ line=$(grep -En "fw.* start" /etc/init.d/firewall | cut -d ":" -f 1)
+ sed -i "${line}a\\. $CRASHDIR/task/affirewall" /etc/init.d/firewall
+ } &
+ exit 0
+else
+ . "$CRASHDIR"/starts/start_error.sh
+ "$CRASHDIR"/start.sh stop
+fi
diff --git a/scripts/starts/bfstart.sh b/scripts/starts/bfstart.sh
new file mode 100644
index 00000000..294e1418
--- /dev/null
+++ b/scripts/starts/bfstart.sh
@@ -0,0 +1,139 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+#初始化目录
+[ -z "$CRASHDIR" ] && CRASHDIR=$( cd $(dirname $0);cd ..;pwd)
+. "$CRASHDIR"/libs/get_config.sh
+[ -z "$BINDIR" -o -z "$TMPDIR" -o -z "$COMMAND" ] && . "$CRASHDIR"/init.sh >/dev/null 2>&1
+[ ! -f "$TMPDIR" ] && mkdir -p "$TMPDIR"
+#加载工具
+. "$CRASHDIR"/libs/check_cmd.sh
+. "$CRASHDIR"/libs/check_target.sh
+. "$CRASHDIR"/libs/logger.sh
+. "$CRASHDIR"/libs/web_get_bin.sh
+. "$CRASHDIR"/libs/compare.sh
+. "$CRASHDIR"/starts/check_geo.sh
+. "$CRASHDIR"/starts/check_core.sh
+#缺省值
+[ -z "$redir_mod" ] && [ "$USER" = "root" -o "$USER" = "admin" ] && redir_mod='Redir模式'
+[ -z "$dns_mod" ] && dns_mod='redir_host'
+[ -z "$redir_mod" ] && firewall_area='4'
+
+makehtml() { #生成面板跳转文件
+ cat >"$BINDIR"/ui/index.html <
+
+
+
+
+
+
+
+ ShellCrash面板提示
+
+
+
+
您还未安装本地面板
+
请在脚本更新功能中(9-4)安装
或者使用在线面板:
+
+
+&1 | grep \"address\" | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
+ [ -z "$host_pac" ] && host_pac=$(ip a 2>&1 | grep -w 'inet' | grep 'global' | grep -E ' 1(92|0|72)\.' | sed 's/.*inet.//g' | sed 's/\/[0-9][0-9].*$//g' | head -n 1)
+ cat >"$TMPDIR"/shellcrash_pac </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
+#清理debug日志
+rm -rf /tmp/ShellCrash/debug.log
+rm -rf "$CRASHDIR"/debug.log
+exit 0
+
diff --git a/scripts/starts/check_cnip.sh b/scripts/starts/check_cnip.sh
new file mode 100644
index 00000000..cda13078
--- /dev/null
+++ b/scripts/starts/check_cnip.sh
@@ -0,0 +1,24 @@
+
+ck_cn_ipv4() { #CN-IP绕过
+ check_geo cn_ip.txt china_ip_list.txt
+ [ -f "$BINDIR"/cn_ip.txt ] && [ "$firewall_mod" = iptables ] && {
+ # see https://raw.githubusercontent.com/Hackl0us/GeoIP2-CN/release/CN-ip-cidr.txt
+ echo "create cn_ip hash:net family inet hashsize 10240 maxelem 10240" >"$TMPDIR"/cn_ip.ipset
+ awk '!/^$/&&!/^#/{printf("add cn_ip %s'" "'\n",$0)}' "$BINDIR"/cn_ip.txt >>"$TMPDIR"/cn_ip.ipset
+ ipset destroy cn_ip >/dev/null 2>&1
+ ipset -! restore <"$TMPDIR"/cn_ip.ipset
+ rm -rf "$TMPDIR"/cn_ip.ipset
+ }
+}
+ck_cn_ipv6() { #CN-IPV6绕过
+ check_geo cn_ipv6.txt china_ipv6_list.txt
+ [ -f "$BINDIR"/cn_ipv6.txt ] && [ "$firewall_mod" = iptables ] && {
+ #ipv6
+ #see https://ispip.clang.cn/all_cn_ipv6.txt
+ echo "create cn_ip6 hash:net family inet6 hashsize 5120 maxelem 5120" >"$TMPDIR"/cn_ipv6.ipset
+ awk '!/^$/&&!/^#/{printf("add cn_ip6 %s'" "'\n",$0)}' "$BINDIR"/cn_ipv6.txt >>"$TMPDIR"/cn_ipv6.ipset
+ ipset destroy cn_ip6 >/dev/null 2>&1
+ ipset -! restore <"$TMPDIR"/cn_ipv6.ipset
+ rm -rf "$TMPDIR"/cn_ipv6.ipset
+ }
+}
\ No newline at end of file
diff --git a/scripts/starts/check_core.sh b/scripts/starts/check_core.sh
new file mode 100644
index 00000000..6bf52c44
--- /dev/null
+++ b/scripts/starts/check_core.sh
@@ -0,0 +1,18 @@
+
+. "$CRASHDIR"/libs/check_target.sh
+. "$CRASHDIR"/libs/core_tools.sh
+. "$CRASHDIR"/configs/command.env
+
+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 2>/dev/null)" ] && {
+ logger "未找到【$crashcore】核心,正在下载!" 33
+ [ -z "$cpucore" ] && . "$CRASHDIR"/libs/check_cpucore.sh && check_cpucore
+ [ -z "$cpucore" ] && logger 找不到设备的CPU信息,请手动指定处理器架构类型! 31 && exit 1
+ core_webget || logger "核心下载失败,请重新运行或更换安装源!" 31
+ }
+ [ ! -x "$TMPDIR"/CrashCore ] && chmod +x "$TMPDIR"/CrashCore 2>/dev/null #自动授权
+ [ "$start_old" != "ON" -a "$(cat /proc/1/comm)" = "systemd" ] && restorecon -RF "$CRASHDIR" 2>/dev/null #修复SELinux权限问题
+ return 0
+}
diff --git a/scripts/starts/check_geo.sh b/scripts/starts/check_geo.sh
new file mode 100644
index 00000000..bc52f6a1
--- /dev/null
+++ b/scripts/starts/check_geo.sh
@@ -0,0 +1,18 @@
+
+. "$CRASHDIR"/libs/set_config.sh
+
+check_geo() { #查找及下载Geo数据文件
+ [ ! -d "$BINDIR"/ruleset ] && mkdir -p "$BINDIR"/ruleset
+ find --help 2>&1 | grep -q size && find_para=' -size +20' #find命令兼容
+ [ -z "$(find "$BINDIR"/"$1" "$find_para" 2>/dev/null)" ] && {
+ if [ -n "$(find "$CRASHDIR"/"$1" "$find_para" 2>/dev/null)" ]; then
+ mv "$CRASHDIR"/"$1" "$BINDIR"/"$1" #小闪存模式移动文件
+ else
+ logger "未找到${1}文件,正在下载!" 33
+ get_bin "$BINDIR"/"$1" bin/geodata/"$2"
+ [ "$?" = "1" ] && rm -rf "${BINDIR}"/"${1}" && logger "${1}文件下载失败,已退出!请前往更新界面尝试手动下载!" 31 && exit 1
+ geo_v="$(echo "$2" | awk -F "." '{print $1}')_v"
+ setconfig "$geo_v" "$(date +"%Y%m%d")"
+ fi
+ }
+}
\ No newline at end of file
diff --git a/scripts/starts/check_network.sh b/scripts/starts/check_network.sh
new file mode 100644
index 00000000..cef39dfb
--- /dev/null
+++ b/scripts/starts/check_network.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+check_network() { #检查是否联网
+ for text in 223.5.5.5 1.2.4.8 dns.alidns.com doh.pub; do
+ ping -c 3 $text >/dev/null 2>&1 && return 0
+ sleep 5
+ done
+ logger "当前设备无法连接网络,已停止启动!" 33
+ exit 1
+}
\ No newline at end of file
diff --git a/scripts/starts/clash_check.sh b/scripts/starts/clash_check.sh
new file mode 100644
index 00000000..413aae1c
--- /dev/null
+++ b/scripts/starts/clash_check.sh
@@ -0,0 +1,21 @@
+
+clash_check() { #clash启动前检查
+ #检测vless/hysteria协议
+ [ "$crashcore" != "meta" ] && [ -n "$(cat $core_config | grep -oE 'type: vless|type: hysteria')" ] && core_exchange meta 'vless/hy协议'
+ #检测是否存在高级版规则或者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 '当前内核不支持的配置'
+ fi
+ [ "$crashcore" = "clash" ] && [ "$firewall_area" = 2 -o "$firewall_area" = 3 ] && [ -z "$(grep '0:7890' /etc/passwd)" ] &&
+ core_exchange meta '当前内核不支持非root用户启用本机代理'
+ check_core
+ #预下载GeoIP数据库并排除存在自定义数据库链接的情况
+ [ -n "$(grep -oEi 'geoip:' "$CRASHDIR"/yamls/config.yaml)" ] && check_geo Country.mmdb cn_mini.mmdb
+ #预下载GeoSite数据库并排除存在自定义数据库链接的情况
+ [ -n "$(grep -oEi 'geosite:' "$CRASHDIR"/yamls/config.yaml)" ] && check_geo GeoSite.dat geosite.dat
+ #预下载cn.mrs数据库
+ [ "$dns_mod" = "mix" ] || [ "$dns_mod" = "route" ] && ! grep -Eq '^[[:space:]]*cn:' "$CRASHDIR"/yamls/*.yaml && check_geo ruleset/cn.mrs mrs_geosite_cn.mrs
+ return 0
+}
diff --git a/scripts/starts/clash_config_check.sh b/scripts/starts/clash_config_check.sh
new file mode 100644
index 00000000..96e85c80
--- /dev/null
+++ b/scripts/starts/clash_config_check.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+check_config() { #检查clash配置文件
+ #检测节点或providers
+ sed -n "/^proxies:/,/^[a-z]/ { /^[a-z]/d; p; }" "$core_config_new" >"$TMPDIR"/proxies.yaml
+ if ! grep -Eq 'server:|server":|server'\'':' "$TMPDIR"/proxies.yaml && ! grep -q 'proxy-providers:' "$core_config_new"; then
+ echo "-----------------------------------------------"
+ logger "获取到了配置文件【$core_config_new】,但似乎并不包含正确的节点信息!" 31
+ cat "$TMPDIR"/proxies.yaml
+ sleep 1
+ echo "-----------------------------------------------"
+ echo "请尝试使用6-2或者6-3的方式生成配置文件!"
+ exit 1
+ fi
+ rm -rf "$TMPDIR"/proxies.yaml
+ #检测旧格式
+ if cat "$core_config_new" | grep 'Proxy Group:' >/dev/null; then
+ echo "-----------------------------------------------"
+ logger "已经停止对旧格式配置文件的支持!!!" 31
+ echo -e "请使用新格式或者使用【在线生成配置文件】功能!"
+ echo "-----------------------------------------------"
+ exit 1
+ fi
+ #检测不支持的加密协议
+ if cat "$core_config_new" | grep 'cipher: chacha20,' >/dev/null; then
+ echo "-----------------------------------------------"
+ logger "已停止支持chacha20加密,请更换更安全的节点加密协议!" 31
+ echo "-----------------------------------------------"
+ exit 1
+ fi
+ #检测并去除无效策略组
+ [ -n "$url_type" ] && ckcmd xargs && {
+ cat "$core_config_new" | sed '/^rules:/,$d' | grep -A 15 "\- name:" | xargs | sed 's/- name: /\n/g' | sed 's/ type: .*proxies: /#/g' | sed 's/- //g' | grep -E '#DIRECT $|#DIRECT$' | grep -Ev '全球直连|direct|Direct' | awk -F '#' '{print $1}' >"$TMPDIR"/clash_proxies
+ while read line; do
+ sed -i "/- $line/d" "$core_config_new"
+ sed -i "/- name: $line/,/- DIRECT/d" "$core_config_new"
+ done <"$TMPDIR"/clash_proxies
+ rm -rf "$TMPDIR"/clash_proxies
+ }
+}
\ No newline at end of file
diff --git a/scripts/starts/clash_modify.sh b/scripts/starts/clash_modify.sh
new file mode 100644
index 00000000..e08e9be1
--- /dev/null
+++ b/scripts/starts/clash_modify.sh
@@ -0,0 +1,241 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+#修饰clash配置文件
+modify_yaml() {
+ ##########需要变更的配置###########
+ [ "$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
+ [ "$crashcore" = 'meta' ] && tun_meta=', device: utun, auto-route: false, auto-detect-interface: false'
+ tun="tun: {enable: true, stack: system$tun_meta}"
+ else
+ tun='tun: {enable: false}'
+ fi
+ 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
+ }
+ }
+ #dns配置
+ [ -z "$(cat "$CRASHDIR"/yamls/user.yaml 2>/dev/null | grep '^dns:')" ] && {
+ [ "$crashcore" != meta ] && dns_resolver='223.5.5.5'
+ cat >"$TMPDIR"/dns.yaml </dev/null | grep -v '#' | sed "s/^/ - '/" | sed "s/$/'/" >>"$TMPDIR"/dns.yaml
+ else
+ echo " - '+.*'" >>"$TMPDIR"/dns.yaml #使用fake-ip模拟redir_host
+ fi
+ #mix模式fakeip绕过cn
+ [ "$dns_mod" = "mix" ] && echo ' - "rule-set:cn"' >>"$TMPDIR"/dns.yaml
+ #mix模式和route模式插入分流设置
+ if [ "$dns_mod" = "mix" ] || [ "$dns_mod" = "route" ]; then
+ [ "$dns_protect" != "OFF" ] && dns_final="$dns_fallback" || dns_final="$dns_nameserver"
+ cat >>"$TMPDIR"/dns.yaml <>"$TMPDIR"/dns.yaml <"$TMPDIR"/set.yaml </dev/null)" ]; then
+ #NTP劫持
+ cat >"$TMPDIR"/hosts.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
+ fi
+ #分割配置文件
+ yaml_char='proxies proxy-groups proxy-providers rules rule-providers sub-rules listeners'
+ for char in $yaml_char; do
+ sed -n "/^$char:/,/^[a-z]/ { /^[a-z]/d; p; }" $core_config >"$TMPDIR"/${char}.yaml
+ done
+ #跳过本地tls证书验证
+ [ "$skip_cert" != "OFF" ] && sed -i 's/skip-cert-verify: false/skip-cert-verify: true/' "$TMPDIR"/proxies.yaml ||
+ sed -i 's/skip-cert-verify: true/skip-cert-verify: false/' "$TMPDIR"/proxies.yaml
+ #插入自定义策略组
+ sed -i "/#自定义策略组开始/,/#自定义策略组结束/d" "$TMPDIR"/proxy-groups.yaml
+ sed -i "/#自定义策略组/d" "$TMPDIR"/proxy-groups.yaml
+ [ -n "$(grep -Ev '^#' "$CRASHDIR"/yamls/proxy-groups.yaml 2>/dev/null)" ] && {
+ #获取空格数
+ space_name=$(grep -aE '^ *- \{?name: ' "$TMPDIR"/proxy-groups.yaml | head -n 1 | grep -oE '^ *')
+ space_proxy="$space_name "
+ #合并自定义策略组到proxy-groups.yaml
+ cat "$CRASHDIR"/yamls/proxy-groups.yaml | sed "/^#/d" | sed "s/#.*//g" | sed '1i\ #自定义策略组开始' | sed '$a\ #自定义策略组结束' | sed "s/^ */${space_name} /g" | sed "s/^ *- /${space_proxy}- /g" | sed "s/^ *- name: /${space_name}- name: /g" | sed "s/^ *- {name: /${space_name}- {name: /g" >"$TMPDIR"/proxy-groups_add.yaml
+ cat "$TMPDIR"/proxy-groups.yaml >>"$TMPDIR"/proxy-groups_add.yaml
+ mv -f "$TMPDIR"/proxy-groups_add.yaml "$TMPDIR"/proxy-groups.yaml
+ oldIFS="$IFS"
+ grep "\- name: " "$CRASHDIR"/yamls/proxy-groups.yaml | sed "/^#/d" | while read line; do #将自定义策略组插入现有的proxy-group
+ new_group=$(echo $line | grep -Eo '^ *- name:.*#' | cut -d'#' -f1 | sed 's/.*name: //g')
+ proxy_groups=$(echo $line | grep -Eo '#.*' | sed "s/#//")
+ IFS="#"
+ for name in $proxy_groups; do
+ line_a=$(grep -n "\- name: $name" "$TMPDIR"/proxy-groups.yaml | head -n 1 | awk -F: '{print $1}') #获取group行号
+ [ -n "$line_a" ] && {
+ line_b=$(grep -A 8 "\- name: $name" "$TMPDIR"/proxy-groups.yaml | grep -n "proxies:$" | head -n 1 | awk -F: '{print $1}') #获取proxies行号
+ line_c=$((line_a + line_b - 1)) #计算需要插入的行号
+ space=$(sed -n "$((line_c + 1))p" "$TMPDIR"/proxy-groups.yaml | grep -oE '^ *') #获取空格数
+ [ "$line_c" -gt 2 ] && sed -i "${line_c}a\\${space}- ${new_group} #自定义策略组" "$TMPDIR"/proxy-groups.yaml
+ }
+ done
+ IFS="$oldIFS"
+ done
+ }
+ #插入自定义代理
+ sed -i "/#自定义代理/d" "$TMPDIR"/proxies.yaml
+ sed -i "/#自定义代理/d" "$TMPDIR"/proxy-groups.yaml
+ [ -n "$(grep -Ev '^#' "$CRASHDIR"/yamls/proxies.yaml 2>/dev/null)" ] && {
+ space_proxy=$(cat "$TMPDIR"/proxies.yaml | grep -aE '^ *- ' | head -n 1 | grep -oE '^ *') #获取空格数
+ cat "$CRASHDIR"/yamls/proxies.yaml | sed "s/^ *- /${space_proxy}- /g" | sed "/^#/d" | sed "/^ *$/d" | sed 's/#.*/ #自定义代理/g' >>"$TMPDIR"/proxies.yaml #插入节点
+ oldIFS="$IFS"
+ cat "$CRASHDIR"/yamls/proxies.yaml | sed "/^#/d" | while read line; do #将节点插入proxy-group
+ proxy_name=$(echo $line | grep -Eo 'name: .+, ' | cut -d',' -f1 | sed 's/name: //g')
+ proxy_groups=$(echo $line | grep -Eo '#.*' | sed "s/#//")
+ IFS="#"
+ for name in $proxy_groups; do
+ line_a=$(grep -n "\- name: $name" "$TMPDIR"/proxy-groups.yaml | head -n 1 | awk -F: '{print $1}') #获取group行号
+ [ -n "$line_a" ] && {
+ line_b=$(grep -A 8 "\- name: $name" "$TMPDIR"/proxy-groups.yaml | grep -n "proxies:$" | head -n 1 | awk -F: '{print $1}') #获取proxies行号
+ line_c=$((line_a + line_b - 1)) #计算需要插入的行号
+ space=$(sed -n "$((line_c + 1))p" "$TMPDIR"/proxy-groups.yaml | grep -oE '^ *') #获取空格数
+ [ "$line_c" -gt 2 ] && sed -i "${line_c}a\\${space}- ${proxy_name} #自定义代理" "$TMPDIR"/proxy-groups.yaml
+ }
+ done
+ IFS="$oldIFS"
+ done
+ }
+ #添加自定义入站
+ [ "$vms_service" = ON ] || [ "$sss_service" = ON ] && {
+ . "$CRASHDIR"/configs/gateway.cfg
+ . "$CRASHDIR"/libs/meta_listeners.sh
+ }
+ #节点绕过功能支持
+ sed -i "/#节点绕过/d" "$TMPDIR"/rules.yaml
+ [ "$proxies_bypass" = "ON" ] && {
+ cat "$TMPDIR"/proxies.yaml | sed '/^proxy-/,$d' | sed '/^rule-/,$d' | grep -v '^\s*#' | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | awk '!a[$0]++' | sed 's/^/\ -\ IP-CIDR,/g' | sed 's|$|/32,DIRECT,no-resolve #节点绕过|g' >>"$TMPDIR"/proxies_bypass
+ cat "$TMPDIR"/proxies.yaml | sed '/^proxy-/,$d' | sed '/^rule-/,$d' | grep -v '^\s*#' | grep -vE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -oE '[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?' | awk '!a[$0]++' | sed 's/^/\ -\ DOMAIN,/g' | sed 's/$/,DIRECT #节点绕过/g' >>"$TMPDIR"/proxies_bypass
+ cat "$TMPDIR"/rules.yaml >>"$TMPDIR"/proxies_bypass
+ mv -f "$TMPDIR"/proxies_bypass "$TMPDIR"/rules.yaml
+ }
+ #插入自定义规则
+ sed -i "/#自定义规则/d" "$TMPDIR"/rules.yaml
+ [ -s "$CRASHDIR"/yamls/rules.yaml ] && {
+ cat "$CRASHDIR"/yamls/rules.yaml | sed "/^#/d" | sed '$a\' | sed 's/$/ #自定义规则/g' >"$TMPDIR"/rules.add
+ cat "$TMPDIR"/rules.yaml >>"$TMPDIR"/rules.add
+ mv -f "$TMPDIR"/rules.add "$TMPDIR"/rules.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
+ }
+ #对齐rules中的空格
+ sed -i 's/^ *-/ -/g' "$TMPDIR"/rules.yaml
+ #合并文件
+ [ -s "$CRASHDIR"/yamls/user.yaml ] && {
+ yaml_user="$CRASHDIR"/yamls/user.yaml
+ #set和user去重,且优先使用user.yaml
+ cp -f "$TMPDIR"/set.yaml "$TMPDIR"/set_bak.yaml
+ for char in mode allow-lan log-level tun experimental external-ui-url interface-name dns store-selected unified-delay; do
+ [ -n "$(grep -E "^$char" $yaml_user)" ] && sed -i "/^$char/d" "$TMPDIR"/set.yaml
+ done
+ }
+ [ -s "$TMPDIR"/dns.yaml ] && yaml_dns="$TMPDIR"/dns.yaml
+ [ -s "$TMPDIR"/hosts.yaml ] && yaml_hosts="$TMPDIR"/hosts.yaml
+ [ -s "$CRASHDIR"/yamls/others.yaml ] && yaml_others="$CRASHDIR"/yamls/others.yaml
+ yaml_add=
+ for char in $yaml_char; do #将额外配置文件合并
+ [ -s "$TMPDIR"/${char}.yaml ] && {
+ sed -i "1i\\${char}:" "$TMPDIR"/${char}.yaml
+ yaml_add="$yaml_add $TMPDIR/${char}.yaml"
+ }
+ done
+ #合并完整配置文件
+ cut -c 1- "$TMPDIR"/set.yaml $yaml_dns $yaml_hosts $yaml_user $yaml_others $yaml_add >"$TMPDIR"/config.yaml
+ #测试自定义配置文件
+ "$TMPDIR"/CrashCore -t -d "$BINDIR" -f "$TMPDIR"/config.yaml >/dev/null
+ if [ "$?" != 0 ]; then
+ logger "$("$TMPDIR"/CrashCore -t -d "$BINDIR" -f "$TMPDIR"/config.yaml | grep -Eo 'error.*=.*')" 31
+ logger "自定义配置文件校验失败!将使用基础配置文件启动!" 33
+ logger "错误详情请参考 "$TMPDIR"/error.yaml 文件!" 33
+ mv -f "$TMPDIR"/config.yaml "$TMPDIR"/error.yaml >/dev/null 2>&1
+ sed -i "/#自定义策略组开始/,/#自定义策略组结束/d" "$TMPDIR"/proxy-groups.yaml
+ mv -f "$TMPDIR"/set_bak.yaml "$TMPDIR"/set.yaml >/dev/null 2>&1
+ #合并基础配置文件
+ cut -c 1- "$TMPDIR"/set.yaml $yaml_dns $yaml_add >"$TMPDIR"/config.yaml
+ sed -i "/#自定义/d" "$TMPDIR"/config.yaml
+ fi
+ #建立软连接
+ [ ""$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
diff --git a/scripts/starts/core_config.sh b/scripts/starts/core_config.sh
new file mode 100644
index 00000000..de1bd553
--- /dev/null
+++ b/scripts/starts/core_config.sh
@@ -0,0 +1,103 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+. "$CRASHDIR"/libs/urlencode.sh
+. "$CRASHDIR"/libs/check_target.sh
+. "$CRASHDIR"/libs/web_get_bin.sh
+. "$CRASHDIR"/libs/compare.sh
+. "$CRASHDIR"/libs/set_config.sh
+
+update_servers() { #更新servers.list
+ get_bin "$TMPDIR"/servers.list public/servers.list
+ [ "$?" = 0 ] && mv -f "$TMPDIR"/servers.list "$CRASHDIR"/configs/servers.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"
+ elif [ "$crashcore" = meta ]; then
+ user_agent="clash.meta/mihomo/$core_v"
+ else
+ user_agent="clash"
+ fi
+ }
+ [ "$user_agent" = "none" ] && unset user_agent
+}
+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}')
+ gen_ua
+ #如果传来的是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
+ Https="${Server}/sub?target=${target}&${Server_ua}=${user_agent}&insert=true&new_name=true&scv=true&udp=true&${urlencodeUrl}"
+ url_type=true
+ fi
+ #输出
+ echo "-----------------------------------------------"
+ logger "正在连接服务器获取【$target】配置文件…………"
+ echo -e "链接地址为:\033[4;32m$Https\033[0m"
+ echo 可以手动复制该链接到浏览器打开并查看数据是否正常!
+ #获取在线config文件
+ core_config_new="$TMPDIR"/"$target"_config."$format"
+ rm -rf "$core_config_new"
+ webget "$core_config_new" "$Https" echoon rediron skipceron "$user_agent"
+ if [ "$?" != "0" ]; then
+ if [ -z "$url_type" ]; then
+ echo "-----------------------------------------------"
+ logger "配置文件获取失败!" 31
+ echo -e "\033[31m请尝试使用【在线生成配置文件】功能!\033[0m"
+ echo "-----------------------------------------------"
+ exit 1
+ else
+ if [ -n "$retry" ] && [ "$retry" -ge 3 ]; then
+ logger "无法获取配置文件,请检查链接格式以及网络连接状态!" 31
+ echo -e "\033[32m也可用浏览器下载以上链接后,使用WinSCP手动上传到/tmp目录后执行crash命令本地导入!\033[0m"
+ exit 1
+ else
+ retry=$((retry + 1))
+ logger "配置文件获取失败!" 31
+ if [ "$retry" = 1 ]; then
+ echo -e "\033[32m尝试更新服务器列表并使用其他服务器获取配置!\033[0m"
+ update_servers
+ else
+ echo -e "\033[32m尝试使用其他服务器获取配置!\033[0m"
+ fi
+ echo -e "正在重试\033[33m第$retry次/共3次!\033[0m"
+ if [ "$server_link" -ge 4 ]; then
+ server_link=0
+ fi
+ server_link=$((server_link + 1))
+ setconfig server_link $server_link
+ Https=""
+ get_core_config
+ fi
+ fi
+ else
+ Https=""
+ if echo "$crashcore" | grep -q 'singbox'; then
+ . "$CRASHDIR"/starts/singbox_config_check.sh
+ else
+ . "$CRASHDIR"/starts/clash_config_check.sh
+ fi
+ check_config
+ #如果不同则备份并替换文件
+ if [ -s "$core_config" ]; then
+ compare "$core_config_new" "$core_config"
+ [ "$?" = 0 ] || mv -f "$core_config" "$core_config".bak && mv -f "$core_config_new" "$core_config"
+ else
+ mv -f "$core_config_new" "$core_config"
+ fi
+ echo -e "\033[32m已成功获取配置文件!\033[0m"
+ fi
+ return 0
+}
diff --git a/scripts/starts/core_exchange.sh b/scripts/starts/core_exchange.sh
new file mode 100644
index 00000000..c52ee5b6
--- /dev/null
+++ b/scripts/starts/core_exchange.sh
@@ -0,0 +1,11 @@
+
+core_exchange() { #升级为高级内核
+ #$1:目标内核 $2:提示语句
+ logger "检测到${2}!将改为使用${1}核心启动!" 33
+ rm -rf "$TMPDIR"/CrashCore
+ rm -rf "$BINDIR"/CrashCore
+ rm -rf "$BINDIR"/CrashCore.tar.gz
+ crashcore="$1"
+ setconfig crashcore "$1"
+ echo "-----------------------------------------------"
+}
diff --git a/scripts/starts/fw_getlanip.sh b/scripts/starts/fw_getlanip.sh
new file mode 100644
index 00000000..1e5d6aa4
--- /dev/null
+++ b/scripts/starts/fw_getlanip.sh
@@ -0,0 +1,30 @@
+
+getlanip() { #获取局域网host地址
+ i=1
+ while [ "$i" -le "20" ]; do
+ host_ipv4=$(ip a 2>&1 | grep -w 'inet' | grep 'global' | grep 'brd' | grep -Ev 'utun|iot|peer|docker|podman|virbr|vnet|ovs|vmbr|veth|vmnic|vboxnet|lxcbr|xenbr|vEthernet' | grep -E ' 1(92|0|72)\.' | sed 's/.*inet.//g' | sed 's/br.*$//g' | sed 's/metric.*$//g') #ipv4局域网网段
+ [ "$ipv6_redir" = "ON" ] && host_ipv6=$(ip a 2>&1 | grep -w 'inet6' | grep -E 'global' | sed 's/.*inet6.//g' | sed 's/scope.*$//g') #ipv6公网地址段
+ [ -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
+ #添加自定义ipv4局域网网段
+ if [ "$replace_default_host_ipv4" == "ON" ]; then
+ host_ipv4="$cust_host_ipv4"
+ else
+ host_ipv4="$host_ipv4$cust_host_ipv4"
+ 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_ipv6="fe80::/10 fd00::/8 $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)
+ [ -z "$local_ipv4" ] && local_ipv4=$(ip route 2>&1 | grep -Eo 'src.*' | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | sort -u)
+ #保留地址
+ [ -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
new file mode 100644
index 00000000..5e0b4681
--- /dev/null
+++ b/scripts/starts/fw_iptables.sh
@@ -0,0 +1,288 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+start_ipt_route() { #iptables-route通用工具
+ #$1:iptables/ip6tables $2:所在的表(nat/mangle) $3:所在的链(OUTPUT/PREROUTING) $4:新创建的shellcrash链表 $5:tcp/udp/all
+ #区分ipv4/ipv6
+ [ "$1" = 'iptables' ] && {
+ RESERVED_IP=$reserve_ipv4
+ HOST_IP=$host_ipv4
+ [ "$3" = 'OUTPUT' ] && HOST_IP="127.0.0.0/8 $local_ipv4"
+ [ "$4" = 'shellcrash_vm' ] && HOST_IP="$vm_ipv4"
+ iptables -h | grep -q '\-w' && w='-w' || w=''
+ }
+ [ "$1" = 'ip6tables' ] && {
+ RESERVED_IP=$reserve_ipv6
+ HOST_IP=$host_ipv6
+ [ "$3" = 'OUTPUT' ] && HOST_IP="::1 $host_ipv6"
+ ip6tables -h | grep -q '\-w' && w='-w' || w=''
+ }
+ #创建新的shellcrash链表
+ "$1" $w -t "$2" -N "$4"
+ #过滤dns
+ "$1" $w -t "$2" -A "$4" -p tcp --dport 53 -j RETURN
+ "$1" $w -t "$2" -A "$4" -p udp --dport 53 -j RETURN
+ #防回环
+ "$1" $w -t "$2" -A "$4" -m mark --mark $routing_mark -j RETURN
+ [ "$3" = 'OUTPUT' ] && for gid in 453 7890; do
+ "$1" $w -t "$2" -A "$4" -m owner --gid-owner $gid -j RETURN
+ 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
+ #跳过目标保留地址及目标本机网段
+ for ip in $HOST_IP $RESERVED_IP; do
+ "$1" $w -t "$2" -A "$4" -d $ip -j RETURN
+ done
+ #绕过CN_IP
+ [ "$1" = iptables ] && [ "$dns_mod" != "fake-ip" ] && [ "$cn_ip_route" = "ON" ] && [ -f "$BINDIR"/cn_ip.txt ] && "$1" $w -t "$2" -A "$4" -m set --match-set cn_ip dst -j RETURN 2>/dev/null
+ [ "$1" = ip6tables ] && [ "$dns_mod" != "fake-ip" ] && [ "$cn_ip_route" = "ON" ] && [ -f "$BINDIR"/cn_ipv6.txt ] && "$1" $w -t "$2" -A "$4" -m set --match-set cn_ip6 dst -j RETURN 2>/dev/null
+ #局域网mac地址黑名单过滤
+ [ "$3" = 'PREROUTING' ] && [ "$macfilter_type" != "白名单" ] && {
+ [ -s "$CRASHDIR"/configs/mac ] &&
+ for mac in $(cat "$CRASHDIR"/configs/mac); do
+ "$1" $w -t "$2" -A "$4" -m mac --mac-source $mac -j RETURN
+ done
+ [ -s "$CRASHDIR"/configs/ip_filter ] && [ "$1" = 'iptables' ] &&
+ for ip in $(cat "$CRASHDIR"/configs/ip_filter); do
+ "$1" $w -t "$2" -A "$4" -s $ip -j RETURN
+ done
+ }
+ #tcp&udp分别进代理链
+ proxy_set() {
+ if [ "$3" = 'PREROUTING' ] && [ "$4" != 'shellcrash_vm' ] && [ "$macfilter_type" = "白名单" ] && [ -n "$(cat $CRASHDIR/configs/mac $CRASHDIR/configs/ip_filter 2>/dev/null)" ]; then
+ [ -s "$CRASHDIR"/configs/mac ] &&
+ for mac in $(cat "$CRASHDIR"/configs/mac); do
+ "$1" $w -t "$2" -A "$4" -p "$5" -m mac --mac-source $mac -j $JUMP
+ done
+ [ -s "$CRASHDIR"/configs/ip_filter ] && [ "$1" = 'iptables' ] &&
+ for ip in $(cat "$CRASHDIR"/configs/ip_filter); do
+ "$1" $w -t "$2" -A "$4" -p "$5" -s $ip -j $JUMP
+ done
+ else
+ for ip in $HOST_IP; do #仅限指定网段流量
+ "$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"
+ [ "$dns_mod" = "mix" -o "$dns_mod" = "fake-ip" ] && [ "$common_ports" = "ON" ] && [ "$1" = ip6tables ] && "$1" $w -t "$2" -I "$3" -p "$5" -d fc00::/16 -j "$4"
+ }
+ [ "$5" = "tcp" -o "$5" = "all" ] && proxy_set "$1" "$2" "$3" "$4" tcp
+ [ "$5" = "udp" -o "$5" = "all" ] && proxy_set "$1" "$2" "$3" "$4" udp
+}
+start_ipt_dns() { #iptables-dns通用工具
+ #$1:iptables/ip6tables $2:所在的表(OUTPUT/PREROUTING) $3:新创建的shellcrash表
+ #区分ipv4/ipv6
+ [ "$1" = 'iptables' ] && {
+ HOST_IP="$host_ipv4"
+ [ "$2" = 'OUTPUT' ] && HOST_IP="127.0.0.0/8 $local_ipv4"
+ [ "$3" = 'shellcrash_vm_dns' ] && HOST_IP="$vm_ipv4"
+ iptables -h | grep -q '\-w' && w='-w' || w=''
+ }
+ [ "$1" = 'ip6tables' ] && {
+ HOST_IP=$host_ipv6
+ ip6tables -h | grep -q '\-w' && w='-w' || w=''
+ }
+ "$1" $w -t nat -N "$3"
+ #防回环
+ "$1" $w -t nat -A "$3" -m mark --mark $routing_mark -j RETURN
+ [ "$2" = 'OUTPUT' ] && for gid in 453 7890; do
+ "$1" $w -t nat -A "$3" -m owner --gid-owner $gid -j RETURN
+ done
+ [ "$firewall_area" = 5 ] && {
+ "$1" $w -t nat -A "$3" -p tcp -s $bypass_host -j RETURN
+ "$1" $w -t nat -A "$3" -p udp -s $bypass_host -j RETURN
+ }
+ #局域网mac地址黑名单过滤
+ [ "$2" = 'PREROUTING' ] && [ "$macfilter_type" != "白名单" ] && {
+ [ -s "$CRASHDIR"/configs/mac ] &&
+ for mac in $(cat "$CRASHDIR"/configs/mac); do
+ "$1" $w -t nat -A "$3" -m mac --mac-source $mac -j RETURN
+ done
+ [ -s "$CRASHDIR"/configs/ip_filter ] && [ "$1" = 'iptables' ] &&
+ for ip in $(cat "$CRASHDIR"/configs/ip_filter); do
+ "$1" $w -t nat -A "$3" -s $ip -j RETURN
+ done
+ }
+ if [ "$2" = 'PREROUTING' ] && [ "$3" != 'shellcrash_vm_dns' ] && [ "$macfilter_type" = "白名单" ] && [ -n "$(cat $CRASHDIR/configs/mac $CRASHDIR/configs/ip_filter 2>/dev/null)" ]; then
+ [ -s "$CRASHDIR"/configs/mac ] &&
+ for mac in $(cat "$CRASHDIR"/configs/mac); do
+ "$1" $w -t nat -A "$3" -p tcp -m mac --mac-source $mac -j REDIRECT --to-ports "$dns_redir_port"
+ "$1" $w -t nat -A "$3" -p udp -m mac --mac-source $mac -j REDIRECT --to-ports "$dns_redir_port"
+ done
+ [ -s "$CRASHDIR"/configs/ip_filter ] && [ "$1" = 'iptables' ] &&
+ for ip in $(cat "$CRASHDIR"/configs/ip_filter); do
+ "$1" $w -t nat -A "$3" -p tcp -s $ip -j REDIRECT --to-ports "$dns_redir_port"
+ "$1" $w -t nat -A "$3" -p udp -s $ip -j REDIRECT --to-ports "$dns_redir_port"
+ done
+ else
+ for ip in $HOST_IP; do #仅限指定网段流量
+ "$1" $w -t nat -A "$3" -p tcp -s $ip -j REDIRECT --to-ports "$dns_redir_port"
+ "$1" $w -t nat -A "$3" -p udp -s $ip -j REDIRECT --to-ports "$dns_redir_port"
+ done
+ fi
+ [ "$1" = 'ip6tables' ] && { #屏蔽外部请求
+ "$1" $w -t nat -A "$3" -p tcp -j RETURN
+ "$1" $w -t nat -A "$3" -p udp -j RETURN
+ }
+ "$1" $w -t nat -I "$2" -p tcp --dport 53 -j "$3"
+ "$1" $w -t nat -I "$2" -p udp --dport 53 -j "$3"
+}
+start_ipt_wan() { #iptables公网防火墙
+ ckcmd iptables && iptables -h | grep -q '\-w' && iptable='iptables -w' || iptable=iptables
+ ckcmd ip6tables && ip6tables -h | grep -q '\-w' && ip6table='ip6tables -w' || ip6table=ip6tables
+ ipt_wan_accept(){
+ $iptable -I INPUT -p "$1" -m multiport --dports "$accept_ports" -j ACCEPT
+ ckcmd ip6tables && $ip6table -I INPUT -p "$1" -m multiport --dports "$accept_ports" -j ACCEPT
+ }
+ ipt_wan_reject(){
+ $iptable -I INPUT -p "$1" -m multiport --dports "$reject_ports" -j REJECT
+ ckcmd ip6tables && $ip6table -I INPUT -p "$1" -m multiport --dports "$reject_ports" -j REJECT
+ }
+ #端口拦截
+ reject_ports="$mix_port,$db_port,$dns_port"
+ ipt_wan_reject tcp
+ ipt_wan_reject udp
+ #端口放行
+ [ -f "$CRASHDIR"/configs/gateway.cfg ] && . "$CRASHDIR"/configs/gateway.cfg
+ accept_ports=$(echo "$fw_wan_ports,$vms_port,$sss_port" | sed "s/,,/,/g ;s/^,// ;s/,$//")
+ [ -n "$accept_ports" ] && {
+ ipt_wan_accept tcp
+ ipt_wan_accept udp
+ }
+ #局域网请求放行
+ for ip in $host_ipv4; do
+ $iptable -I INPUT -s $ip -j ACCEPT
+ done
+ ckcmd ip6tables && for ip in $host_ipv6; do
+ $ip6table -I INPUT -s $ip -j ACCEPT
+ done
+ #本机请求全放行
+ $iptable -I INPUT -i lo -j ACCEPT
+ ckcmd ip6tables && $ip6table -I INPUT -i lo -j ACCEPT
+}
+start_iptables() { #iptables配置总入口
+ #启动公网访问防火墙
+ [ "$fw_wan" != OFF ] && start_ipt_wan
+ #分模式设置流量劫持
+ [ "$redir_mod" = "Redir模式" -o "$redir_mod" = "混合模式" ] && {
+ JUMP="REDIRECT --to-ports $redir_port" #跳转劫持的具体命令
+ [ "$lan_proxy" = true ] && {
+ start_ipt_route iptables nat PREROUTING shellcrash tcp #ipv4-局域网tcp转发
+ [ "$ipv6_redir" = "ON" ] && {
+ if $ip6table -j REDIRECT -h 2>/dev/null | grep -q '\--to-ports'; then
+ start_ipt_route ip6tables nat PREROUTING shellcrashv6 tcp #ipv6-局域网tcp转发
+ else
+ logger "当前设备内核缺少ip6tables_REDIRECT模块支持,已放弃启动相关规则!" 31
+ fi
+ }
+ }
+ [ "$local_proxy" = true ] && {
+ start_ipt_route iptables nat OUTPUT shellcrash_out tcp #ipv4-本机tcp转发
+ [ "$ipv6_redir" = "ON" ] && {
+ if $ip6table -j REDIRECT -h 2>/dev/null | grep -q '\--to-ports'; then
+ start_ipt_route ip6tables nat OUTPUT shellcrashv6_out tcp #ipv6-本机tcp转发
+ else
+ logger "当前设备内核缺少ip6tables_REDIRECT模块支持,已放弃启动相关规则!" 31
+ fi
+ }
+ }
+ }
+ [ "$redir_mod" = "Tproxy模式" ] && {
+ modprobe xt_TPROXY >/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
+ [ "$lan_proxy" = true ] && start_ipt_route iptables mangle PREROUTING shellcrash_mark all
+ [ "$local_proxy" = true ] && {
+ if [ -n "$(grep -E '^MARK$' /proc/net/ip_tables_targets)" ]; then
+ JUMP="MARK --set-mark $fwmark" #跳转劫持的具体命令
+ start_ipt_route iptables mangle OUTPUT shellcrash_mark_out all
+ $iptable -t mangle -A PREROUTING -m mark --mark $fwmark -p tcp -j TPROXY --on-port $tproxy_port
+ $iptable -t mangle -A PREROUTING -m mark --mark $fwmark -p udp -j TPROXY --on-port $tproxy_port
+ else
+ logger "当前设备内核可能缺少xt_mark模块支持,已放弃启动本机代理相关规则!" 31
+ fi
+ }
+ else
+ logger "当前设备内核可能缺少kmod_ipt_tproxy模块支持,已放弃启动相关规则!" 31
+ fi
+ [ "$ipv6_redir" = "ON" ] && {
+ if $ip6table -j TPROXY -h 2>/dev/null | grep -q '\--on-port'; then
+ JUMP="TPROXY --on-port $tproxy_port --tproxy-mark $fwmark" #跳转劫持的具体命令
+ [ "$lan_proxy" = true ] && start_ipt_route ip6tables mangle PREROUTING shellcrashv6_mark all
+ [ "$local_proxy" = true ] && {
+ if [ -n "$(grep -E '^MARK$' /proc/net/ip6_tables_targets)" ]; then
+ JUMP="MARK --set-mark $fwmark" #跳转劫持的具体命令
+ start_ipt_route ip6tables mangle OUTPUT shellcrashv6_mark_out all
+ $ip6table -t mangle -A PREROUTING -m mark --mark $fwmark -p tcp -j TPROXY --on-port $tproxy_port
+ $ip6table -t mangle -A PREROUTING -m mark --mark $fwmark -p udp -j TPROXY --on-port $tproxy_port
+ else
+ logger "当前设备内核可能缺少xt_mark模块支持,已放弃启动本机代理相关规则!" 31
+ fi
+ }
+ else
+ logger "当前设备内核可能缺少kmod_ipt_tproxy或者xt_mark模块支持,已放弃启动相关规则!" 31
+ fi
+ }
+ }
+ [ "$redir_mod" = "Tun模式" -o "$redir_mod" = "混合模式" -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" = "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
+ start_ipt_route iptables mangle PREROUTING shellcrash_mark $protocol
+ }
+ [ "$local_proxy" = true ] && start_ipt_route iptables mangle OUTPUT shellcrash_mark_out $protocol
+ else
+ logger "当前设备内核可能缺少x_mark模块支持,已放弃启动相关规则!" 31
+ fi
+ [ "$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
+ start_ipt_route ip6tables mangle PREROUTING shellcrashv6_mark $protocol
+ }
+ [ "$local_proxy" = true ] && start_ipt_route ip6tables mangle OUTPUT shellcrashv6_mark_out $protocol
+ else
+ logger "当前设备内核可能缺少xt_mark模块支持,已放弃启动相关规则!" 31
+ fi
+ }
+ }
+ [ "$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转发
+ }
+ #启动DNS劫持
+ [ "$firewall_area" -le 3 ] && {
+ [ "$lan_proxy" = true ] && {
+ start_ipt_dns iptables PREROUTING shellcrash_dns #ipv4-局域网dns转发
+ if $ip6table -j REDIRECT -h 2>/dev/null | grep -q '\--to-ports'; then
+ start_ipt_dns ip6tables PREROUTING shellcrashv6_dns #ipv6-局域网dns转发
+ else
+ $ip6table -I INPUT -p tcp --dport 53 -j REJECT >/dev/null 2>&1
+ $ip6table -I INPUT -p udp --dport 53 -j REJECT >/dev/null 2>&1
+ fi
+ }
+ [ "$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模式" ] && {
+ [ "$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" = "混合模式" ] && {
+ $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模式" ] && {
+ $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
+ }
+ }
+}
diff --git a/scripts/starts/fw_nftables.sh b/scripts/starts/fw_nftables.sh
new file mode 100644
index 00000000..53a9bf53
--- /dev/null
+++ b/scripts/starts/fw_nftables.sh
@@ -0,0 +1,211 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+RESERVED_IP=$(echo $reserve_ipv4 | sed 's/ /, /g')
+RESERVED_IP6=$(echo "$reserve_ipv6 $host_ipv6" | sed 's/ /, /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
+ }
+ }
+}
+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/ /, /g')
+ [ "$1" = 'output' ] && HOST_IP="127.0.0.0/8, $(echo $local_ipv4 | sed 's/ /, /g')"
+ [ "$1" = 'prerouting_vm' ] && HOST_IP="$(echo $vm_ipv4 | sed 's/ /, /g')"
+ #添加新链
+ nft add chain inet shellcrash $1 { type $3 hook $2 priority $4 \; }
+ [ "$1" = 'prerouting_vm' ] && nft add rule inet shellcrash $1 ip saddr != {$HOST_IP} return #仅代理虚拟机流量
+ #过滤dns
+ nft add rule inet shellcrash $1 tcp dport 53 return
+ nft add rule inet shellcrash $1 udp dport 53 return
+ #防回环
+ nft add rule inet shellcrash $1 meta mark $routing_mark return
+ nft add rule inet shellcrash $1 meta skgid 7890 return
+ [ "$firewall_area" = 5 ] && nft add rule inet shellcrash $1 ip saddr $bypass_host return
+ [ -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 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 ip saddr 28.0.0.0/8 return
+ nft add rule inet shellcrash $1 ip daddr {$RESERVED_IP} return #过滤保留地址
+ #过滤局域网设备
+ [ "$1" = 'prerouting' ] && {
+ [ "$macfilter_type" != "白名单" ] && {
+ [ -s "$CRASHDIR"/configs/mac ] && {
+ MAC=$(awk '{printf "%s, ",$1}' "$CRASHDIR"/configs/mac)
+ nft add rule inet shellcrash $1 ether saddr {$MAC} return
+ }
+ [ -s "$CRASHDIR"/configs/ip_filter ] && {
+ FL_IP=$(awk '{printf "%s, ",$1}' "$CRASHDIR"/configs/ip_filter)
+ nft add rule inet shellcrash $1 ip saddr {$FL_IP} return
+ }
+ nft add rule inet shellcrash $1 ip saddr != {$HOST_IP} return #仅代理本机局域网网段流量
+ }
+ [ "$macfilter_type" = "白名单" ] && {
+ [ -s "$CRASHDIR"/configs/mac ] && MAC=$(awk '{printf "%s, ",$1}' "$CRASHDIR"/configs/mac)
+ [ -s "$CRASHDIR"/configs/ip_filter ] && FL_IP=$(awk '{printf "%s, ",$1}' "$CRASHDIR"/configs/ip_filter)
+ if [ -n "$MAC" ] && [ -n "$FL_IP" ]; then
+ nft add rule inet shellcrash $1 ether saddr != {$MAC} ip saddr != {$FL_IP} return
+ elif [ -n "$MAC" ]; then
+ nft add rule inet shellcrash $1 ether saddr != {$MAC} return
+ elif [ -n "$FL_IP" ]; then
+ nft add rule inet shellcrash $1 ip saddr != {$FL_IP} return
+ else
+ nft add rule inet shellcrash $1 ip saddr != {$HOST_IP} return #仅代理本机局域网网段流量
+ fi
+ }
+ }
+ #绕过CN-IP
+ [ "$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
+ }
+ }
+ #局域网ipv6支持
+ if [ "$ipv6_redir" = "ON" -a "$1" = 'prerouting' -a "$firewall_area" != 5 ]; then
+ HOST_IP6=$(echo $host_ipv6 | sed 's/ /, /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/ /, /g')"
+ 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
+ #添加通用路由
+ nft add rule inet shellcrash "$1" "$JUMP"
+ #处理特殊路由
+ [ "$redir_mod" = "混合模式" ] && {
+ 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
+ }
+ #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/ /, /g')
+ HOST_IP6=$(echo $host_ipv6 | sed 's/ /, /g')
+ }
+ [ "$1" = 'output' ] && HOST_IP="127.0.0.0/8, $(echo $local_ipv4 | sed 's/ /, /g')"
+ [ "$1" = 'prerouting_vm' ] && HOST_IP="$(echo $vm_ipv4 | sed 's/ /, /g')"
+ nft add chain inet shellcrash "$1"_dns { type nat hook $2 priority -100 \; }
+ #过滤非dns请求
+ nft add rule inet shellcrash "$1"_dns udp dport != 53 return
+ nft add rule inet shellcrash "$1"_dns tcp dport != 53 return
+ #防回环
+ nft add rule inet shellcrash "$1"_dns meta mark $routing_mark return
+ nft add rule inet shellcrash "$1"_dns meta skgid { 453, 7890 } return
+ [ "$firewall_area" = 5 ] && nft add rule inet shellcrash "$1"_dns ip saddr $bypass_host return
+ nft add rule inet shellcrash "$1"_dns ip saddr != {$HOST_IP} return #屏蔽外部请求
+ [ "$1" = 'prerouting' ] && nft add rule inet shellcrash "$1"_dns ip6 saddr != {$HOST_IP6} return #屏蔽外部请求
+ #过滤局域网设备
+ [ "$1" = 'prerouting' ] && [ -s "$CRASHDIR"/configs/mac ] && {
+ MAC=$(awk '{printf "%s, ",$1}' "$CRASHDIR"/configs/mac)
+ if [ "$macfilter_type" = "黑名单" ]; then
+ nft add rule inet shellcrash "$1"_dns ether saddr {$MAC} return
+ else
+ nft add rule inet shellcrash "$1"_dns ether saddr != {$MAC} return
+ fi
+ }
+ nft add rule inet shellcrash "$1"_dns udp dport 53 redirect to "$dns_redir_port"
+ 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/ /, /g')
+ HOST_IP6=$(echo $host_ipv6 | sed 's/ /, /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/,/, /")
+ [ -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, $dns_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
+}
+start_nftables() { #nftables配置总入口
+ #初始化nftables
+ nft add table inet shellcrash 2>/dev/null
+ nft flush table inet shellcrash 2>/dev/null
+ #公网访问防火墙
+ [ "$fw_wan" != OFF ] && [ "$systype" != 'container' ] && start_nft_wan
+ #启动DNS劫持
+ [ "$firewall_area" -le 3 ] && {
+ [ "$lan_proxy" = true ] && start_nft_dns prerouting prerouting #局域网dns转发
+ [ "$local_proxy" = true ] && start_nft_dns output output #本机dns转发
+ }
+ #分模式设置流量劫持
+ [ "$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) && {
+ 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 ] && {
+ JUMP="meta l4proto {tcp, udp} mark set $fwmark" #跳转劫持的具体命令
+ start_nft_route output output route -150
+ nft add chain inet shellcrash mark_out { type filter hook prerouting priority -100 \; }
+ nft add rule inet shellcrash mark_out meta mark $fwmark meta l4proto {tcp, udp} tproxy to :$tproxy_port
+ }
+ }
+ [ "$tun_statu" = true ] && {
+ [ "$redir_mod" = "Tun模式" ] && JUMP="meta l4proto {tcp, udp} mark set $fwmark" #跳转劫持的具体命令
+ [ "$redir_mod" = "混合模式" ] && JUMP="meta l4proto udp mark set $fwmark" #跳转劫持的具体命令
+ [ "$lan_proxy" = true ] && {
+ start_nft_route prerouting prerouting filter -150
+ #放行流量
+ nft list table inet fw4 >/dev/null 2>&1 || nft add table inet fw4
+ nft list chain inet fw4 forward >/dev/null 2>&1 || nft add chain inet fw4 forward { type filter hook forward priority filter \; } 2>/dev/null
+ nft list chain inet fw4 input >/dev/null 2>&1 || nft add chain inet fw4 input { type filter hook input priority filter \; } 2>/dev/null
+ nft list chain inet fw4 forward | grep -q 'oifname "utun" accept' || nft insert rule inet fw4 forward oifname "utun" accept
+ nft list chain inet fw4 input | grep -q 'iifname "utun" accept' || nft insert rule inet fw4 input iifname "utun" accept
+ }
+ [ "$local_proxy" = true ] && start_nft_route output output route -150
+ }
+ [ "$firewall_area" = 5 ] && {
+ [ "$redir_mod" = "T&U旁路转发" ] && JUMP="meta l4proto {tcp, udp} mark set $fwmark" #跳转劫持的具体命令
+ [ "$redir_mod" = "TCP旁路转发" ] && JUMP="meta l4proto tcp mark set $fwmark" #跳转劫持的具体命令
+ [ "$lan_proxy" = true ] && start_nft_route prerouting prerouting filter -150
+ [ "$local_proxy" = true ] && start_nft_route output output route -150
+ }
+ [ "$vm_redir" = "ON" ] && [ -n "$$vm_ipv4" ] && {
+ start_nft_dns prerouting_vm prerouting
+ JUMP="meta l4proto tcp redirect to $redir_port" #跳转劫持的具体命令
+ start_nft_route prerouting_vm prerouting nat -100
+ }
+}
diff --git a/scripts/starts/fw_start.sh b/scripts/starts/fw_start.sh
new file mode 100644
index 00000000..f0ae831f
--- /dev/null
+++ b/scripts/starts/fw_start.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+#获取局域网host地址
+. "$CRASHDIR"/starts/fw_getlanip.sh && getlanip
+#缺省值
+[ -z "$macfilter_type" ] && macfilter_type='黑名单'
+[ -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 "$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
+}
+#添加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
+}
+#判断代理用途
+[ "$firewall_area" = 2 -o "$firewall_area" = 3 ] && local_proxy=true
+[ "$firewall_area" = 1 -o "$firewall_area" = 3 -o "$firewall_area" = 5 ] && lan_proxy=true
+#防火墙配置
+[ "$firewall_mod" = 'iptables' ] && . "$CRASHDIR"/starts/fw_iptables.sh && start_iptables
+[ "$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
+}
+#移除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]
+}
diff --git a/scripts/starts/fw_stop.sh b/scripts/starts/fw_stop.sh
new file mode 100644
index 00000000..154e40fa
--- /dev/null
+++ b/scripts/starts/fw_stop.sh
@@ -0,0 +1,136 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+#初始化目录
+[ -z "$CRASHDIR" ] && CRASHDIR=$( cd $(dirname $0);cd ..;pwd)
+. "$CRASHDIR"/libs/get_config.sh
+. "$CRASHDIR"/libs/check_cmd.sh
+. "$CRASHDIR"/starts/fw_getlanip.sh && getlanip #获取局域网host地址
+#缺省值
+[ -z "$common_ports" ] && common_ports='ON'
+[ -z "$multiport" ] && multiport='22,80,443,8080,8443'
+[ "$common_ports" = "ON" ] && ports="-m multiport --dports $multiport"
+[ -f "$CRASHDIR"/configs/gateway.cfg ] && . "$CRASHDIR"/configs/gateway.cfg
+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,$dns_port" -j REJECT 2>/dev/null
+ $iptable -D INPUT -p udp -m multiport --dports "$mix_port,$db_port,$dns_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,$dns_port" -j REJECT 2>/dev/null
+ $ip6table -D INPUT -p udp -m multiport --dports "$mix_port,$db_port,$dns_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
+ipset destroy cn_ip6 >/dev/null 2>&1
+#清理路由规则
+ip rule del fwmark $fwmark table $table 2>/dev/null
+ip route flush table $table 2>/dev/null
+ip -6 rule del fwmark $fwmark table $((table + 1)) 2>/dev/null
+ip -6 route flush table $((table + 1)) 2>/dev/null
+#重置nftables相关规则
+ckcmd nft && nft delete table inet shellcrash >/dev/null 2>&1
+#还原防火墙文件
+[ -s /etc/init.d/firewall.bak ] && mv -f /etc/init.d/firewall.bak /etc/init.d/firewall
+#others
+[ "$systype" != 'container' ] && sed -i '/shellcrash-dns-repair/d' /etc/resolv.conf >/dev/null 2>&1
+
diff --git a/scripts/starts/general_init.sh b/scripts/starts/general_init.sh
new file mode 100644
index 00000000..5f547800
--- /dev/null
+++ b/scripts/starts/general_init.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+#初始化目录
+[ -z "$CRASHDIR" ] && CRASHDIR=$( cd $(dirname $0);cd ..;pwd)
+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" #将软链接转化为一般文件
+elif [ -d "/jffs" ]; then
+ 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 ];then
+ cronset "保守模式守护进程"
+else
+ "$CRASHDIR"/start.sh start
+fi
diff --git a/scripts/shellcrash.openrc b/scripts/starts/shellcrash.openrc
similarity index 86%
rename from scripts/shellcrash.openrc
rename to scripts/starts/shellcrash.openrc
index a0b21567..9d0ff118 100644
--- a/scripts/shellcrash.openrc
+++ b/scripts/starts/shellcrash.openrc
@@ -6,7 +6,7 @@ description="Custom proxy service for ShellCrash"
#获取目录
CRASHDIR=$(cat /etc/profile | grep CRASHDIR | awk -F "\"" '{print $2}')
[ -z "$CRASHDIR" ] && CRASHDIR=$(cat ~/.bashrc | grep CRASHDIR | awk -F "\"" '{print $2}')
-source ${CRASHDIR}/configs/command.env #加载启动命令和启动目录
+. ${CRASHDIR}/configs/command.env #加载启动命令和启动目录
# PID 文件
pidfile="/run/shellcrash.pid"
@@ -21,7 +21,7 @@ start() {
# 如果 firewal_area=5 则运行主旁转发脚本
if grep -q 'firewall_area=5' "$CRASHDIR/configs/ShellCrash.cfg" 2>/dev/null; then
- "$CRASHDIR/start.sh" start_firewall
+ "$CRASHDIR"/starts/fw_start.sh
eend $? "Firewall start failed"
return
fi
@@ -34,7 +34,7 @@ start() {
fi
# 必要文件检测
- "$CRASHDIR/start.sh" bfstart
+ "$CRASHDIR"/starts/bfstart.sh
if [ "$?" != "0" ]; then
eend 1 "bfstart check failed"
return
@@ -53,7 +53,7 @@ start() {
[ $ret -ne 0 ] && return
# 启动后操作
- "$CRASHDIR/start.sh" afstart &
+ "$CRASHDIR"/starts/afstart.sh &
}
stop() {
@@ -67,7 +67,7 @@ stop() {
rm -f "${pidfile}"
# 清理 firewall、proxy
- "$CRASHDIR/start.sh" stop_firewall
+ "$CRASHDIR"/starts/fw_stop.sh
eend $?
}
diff --git a/scripts/shellcrash.procd b/scripts/starts/shellcrash.procd
similarity index 79%
rename from scripts/shellcrash.procd
rename to scripts/starts/shellcrash.procd
index f884dd10..ac9b6cb7 100644
--- a/scripts/shellcrash.procd
+++ b/scripts/starts/shellcrash.procd
@@ -8,16 +8,16 @@ USE_PROCD=1
#获取目录
CRASHDIR=$(cat /etc/profile | grep CRASHDIR | awk -F "\"" '{print $2}')
[ -z "$CRASHDIR" ] && CRASHDIR=$(cat ~/.bashrc | grep CRASHDIR | awk -F "\"" '{print $2}')
-source ${CRASHDIR}/configs/command.env #加载启动命令和启动目录
+. "$CRASHDIR"/configs/command.env #加载启动命令和启动目录
start_service() {
if [ -n "$(cat $CRASHDIR/configs/ShellCrash.cfg | grep 'firewall_area=5')" ]; then
- $CRASHDIR/start.sh start_firewall #主旁转发
+ "$CRASHDIR"/starts/fw_start.sh #主旁转发
else
#本机代理用户
[ -n "$(grep 'shellcrash:x:0:7890' /etc/passwd)" ] && USER=shellcrash || USER=root
#检测必须文件
- $CRASHDIR/start.sh bfstart
+ "$CRASHDIR"/starts/bfstart.sh
if [ "$?" = "0" ]; then
#使用procd创建clash后台进程
procd_open_instance
@@ -28,11 +28,11 @@ start_service() {
procd_set_param stdout 0
procd_close_instance
#启动结束执行
- $CRASHDIR/start.sh afstart &
+ "$CRASHDIR"/starts/afstart.sh &
fi
fi
}
stop_service() {
procd_close_instance
- $CRASHDIR/start.sh stop_firewall
+ "$CRASHDIR"/starts/fw_stop.sh
}
diff --git a/scripts/shellcrash.service b/scripts/starts/shellcrash.service
similarity index 65%
rename from scripts/shellcrash.service
rename to scripts/starts/shellcrash.service
index ac2bc3c0..1c0e5faa 100644
--- a/scripts/shellcrash.service
+++ b/scripts/starts/shellcrash.service
@@ -5,12 +5,11 @@ After=network.target
[Service]
Type=simple
User=shellcrash
-User=shellcrash
StandardOutput=null
-ExecStartPre=/etc/ShellCrash/start.sh bfstart
+ExecStartPre=/etc/ShellCrash/starts/bfstart.sh
ExecStart=/etc/ShellCrash/CrashCore run -D /etc/ShellCrash -C /tmp/ShellCrash/jsons >/dev/null
-ExecStartPost=/etc/ShellCrash/start.sh afstart
-ExecStopPost=/etc/ShellCrash/start.sh stop_firewall
+ExecStartPost=/etc/ShellCrash/starts/afstart.sh
+ExecStopPost=/etc/ShellCrash/starts/fw_stop.sh
Restart=on-abnormal
RestartSec=10s
LimitNOFILE=infinity
diff --git a/scripts/starts/singbox_check.sh b/scripts/starts/singbox_check.sh
new file mode 100644
index 00000000..9307664f
--- /dev/null
+++ b/scripts/starts/singbox_check.sh
@@ -0,0 +1,11 @@
+
+singbox_check() { #singbox启动前检查
+ #检测singboxr专属功能
+ [ "$crashcore" != "singboxr" ] && [ -n "$(cat "$CRASHDIR"/jsons/*.json | grep -oE '"shadowsocksr"|"providers"')" ] && {
+ . "$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
+ return 0
+}
\ No newline at end of file
diff --git a/scripts/starts/singbox_config_check.sh b/scripts/starts/singbox_config_check.sh
new file mode 100644
index 00000000..d4b1731d
--- /dev/null
+++ b/scripts/starts/singbox_config_check.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+check_config() { #检查singbox配置文件
+ #检测节点或providers
+ if ! grep -qE '"(socks|http|shadowsocks(r)?|vmess|trojan|wireguard|hysteria(2)?|vless|shadowtls|tuic|ssh|tor|providers|anytls|soduku)"' "$core_config_new"; then
+ echo "-----------------------------------------------"
+ logger "获取到了配置文件【$core_config_new】,但似乎并不包含正确的节点信息!" 31
+ echo "请尝试使用6-2或者6-3的方式生成配置文件!"
+ exit 1
+ fi
+ #删除不兼容的旧版内容
+ [ "$(wc -l <"$core_config_new")" -lt 3 ] && {
+ sed -i 's/^.*"inbounds":/{"inbounds":/' "$core_config_new"
+ sed -i 's/{[^{}]*"dns-out"[^{}]*}//g' "$core_config_new"
+ }
+ #检查不支持的旧版内容
+ grep -q '"sni"' "$core_config_new" && {
+ logger "获取到了不支持的旧版(<1.12)配置文件【$core_config_new】!" 31
+ echo "请尝试使用支持1.12以上版本内核的方式生成配置文件!"
+ exit 1
+ }
+ #检测并去除无效策略组
+ [ -n "$url_type" ] && {
+ #获得无效策略组名称
+ grep -oE '\{"type":"urltest","tag":"[^"]*","outbounds":\["DIRECT"\]' "$core_config_new" | sed -n 's/.*"tag":"\([^"]*\)".*/\1/p' >"$TMPDIR"/singbox_tags
+ #删除策略组
+ sed -i 's/{"type":"urltest","tag":"[^"]*","outbounds":\["DIRECT"\]}//g; s/{"type":"[^"]*","tag":"[^"]*","outbounds":\["DIRECT"\],"url":"[^"]*","interval":"[^"]*","tolerance":[^}]*}//g' "$core_config_new"
+ #删除全部包含策略组名称的规则
+ while read line; do
+ sed -i "s/\"$line\"//g" "$core_config_new"
+ done <"$TMPDIR"/singbox_tags
+ rm -rf "$TMPDIR"/singbox_tags
+ }
+ #清理多余逗号
+ sed -i 's/,\+/,/g; s/\[,/\[/g; s/,]/]/g' "$core_config_new"
+}
diff --git a/scripts/starts/singbox_modify.sh b/scripts/starts/singbox_modify.sh
new file mode 100644
index 00000000..e1c02052
--- /dev/null
+++ b/scripts/starts/singbox_modify.sh
@@ -0,0 +1,394 @@
+#!/bin/sh
+# Copyright (C) Juewuy
+
+ #修饰singbox配置文件
+parse_singbox_dns() { #dns转换
+ first_dns=$(echo "$1" | cut -d',' -f1 | cut -d' ' -f1)
+ type=""
+ server=""
+ port=""
+ case "$first_dns" in
+ *://*)
+ type="${first_dns%%://*}"
+ tmp="${first_dns#*://}"
+ ;;
+ *)
+ type="udp"
+ tmp="$first_dns"
+ ;;
+ esac
+ case "$tmp" in
+ \[*\]*)
+ server="${tmp%%]*}"
+ server="${server#[}"
+ port="${tmp#*\]}"
+ port="${port#:}"
+ ;;
+ *)
+ server="${tmp%%[:/]*}"
+ port="${tmp#*:}"
+ [ "$port" = "$tmp" ] && port=""
+ ;;
+ esac
+ if [ -z "$port" ]; then
+ case "$type" in
+ udp|tcp) port=53 ;;
+ doh|https) port=443 ;;
+ dot|tls) port=853 ;;
+ *) port=53 ;;
+ esac
+ fi
+ # 输出
+ echo '"type": "'"$type"'", "server": "'"$server"'", "server_port": '"$port"','
+}
+modify_json() {
+ #提取配置文件以获得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
+ cat "$TMPDIR"/format.json | sed -n '/"outbounds":/,/^ "[a-z]/p' | sed '$d' >>"$TMPDIR"/jsons/outbounds.json
+ [ "$crashcore" = "singboxr" ] && {
+ echo '{' >"$TMPDIR"/jsons/providers.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
+ }
+ #生成log.json
+ cat >"$TMPDIR"/jsons/log.json <"$TMPDIR"/jsons/add_hosts.json </dev/null | grep -Ev '#|\*|\+|Mijia' | sed '/^\s*$/d' | awk '{printf "\"%s\", ",$1}' | sed 's/, $//')
+ fake_ip_filter_suffix=$(cat ${CRASHDIR}/configs/fake_ip_filter ${CRASHDIR}/configs/fake_ip_filter.list 2>/dev/null | grep -v '.\*' | grep -E '\*|\+' | sed 's/^[*+]\.//' | awk '{printf "\"%s\", ",$1}' | sed 's/, $//')
+ fake_ip_filter_regex=$(cat ${CRASHDIR}/configs/fake_ip_filter ${CRASHDIR}/configs/fake_ip_filter.list 2>/dev/null | grep '.\*' | sed 's/\./\\\\./g' | sed 's/\*/.\*/' | sed 's/^+/.\+/' | awk '{printf "\"%s\", ",$1}' | sed 's/, $//')
+ [ -n "$fake_ip_filter_domain" ] && fake_ip_filter_domain="{ \"domain\": [$fake_ip_filter_domain], \"server\": \"dns_direct\" },"
+ [ -n "$fake_ip_filter_suffix" ] && fake_ip_filter_suffix="{ \"domain_suffix\": [$fake_ip_filter_suffix], \"server\": \"dns_direct\" },"
+ [ -n "$fake_ip_filter_regex" ] && fake_ip_filter_regex="{ \"domain_regex\": [$fake_ip_filter_regex], \"server\": \"dns_direct\" },"
+ proxy_dns='{ "query_type": ["A", "AAAA"], "server": "dns_fakeip", "strategy": "'"$strategy"'", "rewrite_ttl": 1 }'
+ #mix模式插入fakeip过滤规则
+ [ "$dns_mod" = "mix" ] && direct_dns='{ "rule_set": ["cn"], "server": "dns_direct" },'
+ }
+ [ "$dns_mod" = "route" ] && {
+ global_dns=dns_proxy
+ direct_dns='{ "rule_set": ["cn"], "server": "dns_direct" }'
+ }
+ #防泄露设置
+ [ "$dns_protect" = "OFF" ] && sed -i 's/"server": "dns_proxy"/"server": "dns_direct"/g' "$TMPDIR"/jsons/route.json
+ #生成add_rule_set.json
+ [ "$dns_mod" = "mix" ] || [ "$dns_mod" = "route" ] && ! grep -Eq '"tag" *:[[:space:]]*"cn"' "$CRASHDIR"/jsons/*.json && {
+ [ "$crashcore" = "singboxr" ] && srs_path='"path": "./ruleset/cn.srs",'
+ cat >"$TMPDIR"/jsons/add_rule_set.json <"$TMPDIR"/jsons/dns.json <"$TMPDIR"/jsons/add_route.json <"$TMPDIR"/jsons/certificate.json <"$TMPDIR"/jsons/inbounds.json <>"$TMPDIR"/jsons/tun.json <"$TMPDIR"/jsons/add_outbounds.json <"$TMPDIR"/jsons/experimental.json </dev/null)" ] && {
+ cat "$CRASHDIR"/yamls/rules.yaml |
+ sed '/#.*/d' |
+ sed 's/,no-resolve//g' |
+ grep -oE '\-.*,.*,.*' |
+ sed 's/- DOMAIN-SUFFIX,/{ "domain_suffix": [ "/g' |
+ sed 's/- DOMAIN-KEYWORD,/{ "domain_keyword": [ "/g' |
+ sed 's/- IP-CIDR,/{ "ip_cidr": [ "/g' |
+ sed 's/- SRC-IP-CIDR,/{ "._ip_cidr": [ "/g' |
+ sed 's/- DST-PORT,/{ "port": [ "/g' |
+ sed 's/- SRC-PORT,/{ "._port": [ "/g' |
+ sed 's/- GEOIP,/{ "geoip": [ "/g' |
+ sed 's/- GEOSITE,/{ "geosite": [ "/g' |
+ sed 's/- IP-CIDR6,/{ "ip_cidr": [ "/g' |
+ sed 's/- DOMAIN,/{ "domain": [ "/g' |
+ sed 's/- PROCESS-NAME,/{ "process_name": [ "/g' |
+ sed 's/,/" ], "outbound": "/g' |
+ sed 's/$/" },/g' |
+ sed '1i\{ "route": { "rules": [ ' |
+ sed '$s/,$/ ] } }/' >"$TMPDIR"/jsons/cust_add_rules.json
+ [ ! -s "$TMPDIR"/jsons/cust_add_rules.json ] && rm -rf "$TMPDIR"/jsons/cust_add_rules.json
+ }
+ #清理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
+ #跳过本地tls证书验证
+ if [ "$skip_cert" != "OFF" ]; then
+ sed -i 's/"insecure": false/"insecure": true/' "$TMPDIR"/jsons/outbounds.json "$TMPDIR"/jsons/providers.json 2>/dev/null
+ else
+ sed -i 's/"insecure": true/"insecure": false/' "$TMPDIR"/jsons/outbounds.json "$TMPDIR"/jsons/providers.json 2>/dev/null
+ fi
+ #判断可用并修饰outbounds&providers&route.json结尾
+ for file in outbounds providers route; do
+ if [ -n "$(grep ${file} "$TMPDIR"/jsons/${file}.json 2>/dev/null)" ]; then
+ sed -i 's/^ },$/ }/; s/^ ],$/ ]/' "$TMPDIR"/jsons/${file}.json
+ echo '}' >>"$TMPDIR"/jsons/${file}.json
+ else
+ rm -rf "$TMPDIR"/jsons/${file}.json
+ fi
+ done
+ #加载自定义配置文件
+ mkdir -p "$TMPDIR"/jsons_base
+ #以下为覆盖脚本的自定义文件
+ for char in log dns ntp certificate 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 #如果重复则临时备份
+ }
+ done
+ #以下为增量添加的自定义文件
+ for char in others endpoints inbounds outbounds providers route services; do
+ [ -s "$CRASHDIR"/jsons/${char}.json ] && {
+ ln -sf "$CRASHDIR"/jsons/${char}.json "$TMPDIR"/jsons/cust_${char}.json
+ }
+ done
+ #测试自定义配置文件
+ 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')
+ [ "$error_file" = 'add_rules.json' ] && error_file="$CRASHDIR"/yamls/rules.yaml自定义规则 || error_file="$CRASHDIR"/jsons/$error_file
+ logger "自定义配置文件校验失败,请检查【${error_file}】文件!" 31
+ logger "尝试使用基础配置文件启动~" 33
+ #清理自定义配置文件并还原基础配置
+ rm -rf "$TMPDIR"/jsons/cust_*
+ mv -f "$TMPDIR"/jsons_base/* "$TMPDIR"/jsons 2>/dev/null
+ fi
+ #清理缓存
+ rm -rf "$TMPDIR"/*.json
+ rm -rf "$TMPDIR"/jsons_base
+ return 0
+}
diff --git a/scripts/misnap_init.sh b/scripts/starts/snapshot_init.sh
similarity index 57%
rename from scripts/misnap_init.sh
rename to scripts/starts/snapshot_init.sh
index 8a1a69d4..0d566b34 100644
--- a/scripts/misnap_init.sh
+++ b/scripts/starts/snapshot_init.sh
@@ -1,9 +1,9 @@
#!/bin/sh
# Copyright (C) Juewuy
-CRASHDIR="$(uci get firewall.ShellCrash.path | sed 's/\/misnap_init.sh//')"
-profile=/etc/profile
-. "$CRASHDIR"/configs/ShellCrash.cfg
+CRASHDIR="$(uci get firewall.ShellCrash.path | sed 's/\/starts\/snapshot_init.sh//')"
+
+[ -f "$CRASHDIR"/configs/ShellCrash.cfg ] && . "$CRASHDIR"/configs/ShellCrash.cfg
autoSSH(){
#自动开启SSH
@@ -14,7 +14,6 @@ autoSSH(){
[ -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
- mi_autoSSH_pwd=$(grep 'mi_autoSSH_pwd=' $CRASHDIR/configs/ShellCrash.cfg | awk -F "=" '{print $2}')
[ -n "$mi_autoSSH_pwd" ] && echo -e "$mi_autoSSH_pwd\n$mi_autoSSH_pwd" | passwd root
}
#配置nvram
@@ -22,8 +21,8 @@ autoSSH(){
[ "$(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
+ [ -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||' )
@@ -31,9 +30,9 @@ tunfix(){
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}
+ 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 || $CRASHDIR/start.sh loggger "小米Tun模块修复失败!"
+ 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
@@ -47,7 +46,32 @@ auto_clean(){
/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
- rm -rf /data/usr/log
+ sed -i '\#/sec_cfg_bak#{ /^[[:space:]]*#/!s/^/#ShellCrash自动注释 / }' /etc/crontabs/root
+ rm -rf /data/usr/log /data/usr/sec_cfg
+
+}
+auto_start(){
+ #设置init.d服务
+ cp -f "$CRASHDIR"/starts/shellcrash.procd /etc/init.d/shellcrash
+ chmod 755 /etc/init.d/shellcrash
+ #初始化环境变量
+ . "$CRASHDIR"/libs/set_profile.sh && set_profile '/etc/profile'
+ #启动服务
+ if [ ! -f "$CRASHDIR"/.dis_startup ]; then
+ #AX6S/AX6000修复tun功能
+ [ -s "$CRASHDIR"/tools/tun.ko ] && tunfix
+ #小米7000/小米万兆修复tproxy
+ [ -f /etc/init.d/qca-nss-ecm ] && [ "$redir_mod" = 'Tproxy' ] && tproxyfix
+ #自动覆盖根证书文件
+ [ -s "$CRASHDIR"/tools/ca-certificates.crt ] && cp -f "$CRASHDIR"/tools/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
+ #启动服务
+ "$CRASHDIR"/start.sh start
+ /etc/init.d/shellcrash enable
+ fi
+ #启动自定义服务
+ [ -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(){
#等待启动完成
@@ -55,29 +79,9 @@ init(){
sleep 10
done
sleep 20
- #初始化环境变量
- [ -z "$my_alias" ] && my_alias=crash
- sed -i "/ShellCrash\/menu.sh/"d "$profile"
- echo "alias ${my_alias}=\"sh $CRASHDIR/menu.sh\"" >>"$profile"
- sed -i "/export CRASHDIR/d" "$profile"
- echo "export CRASHDIR=\"$CRASHDIR\"" >>"$profile"
autoSSH #软固化功能
auto_clean #自动清理
- #设置init.d服务
- cp -f $CRASHDIR/shellcrash.procd /etc/init.d/shellcrash
- chmod 755 /etc/init.d/shellcrash
- #启动服务
- if [ ! -f $CRASHDIR/.dis_startup ]; then
- #AX6S/AX6000修复tun功能
- [ -s $CRASHDIR/tools/tun.ko ] && tunfix
- #小米7000/小米万兆修复tproxy
- [ -f /etc/init.d/qca-nss-ecm ] && [ -n "$(grep 'redir_mod=Tproxy' $CRASHDIR/configs/ShellCrash.cfg )" ] && tproxyfix
- #自动覆盖根证书文件
- [ -s $CRASHDIR/tools/ca-certificates.crt ] && cp -f $CRASHDIR/tools/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
- #启动服务
- $CRASHDIR/start.sh start
- /etc/init.d/shellcrash enable
- fi
+ [ -s "$CRASHDIR"/start.sh ] && auto_start
}
case "$1" in
@@ -86,7 +90,7 @@ case "$1" in
auto_clean) auto_clean ;;
init) init ;;
*)
- if [ -z $(pidof CrashCore) ];then
+ if [ -z "$(pidof CrashCore)" ];then
init &
fi
;;
diff --git a/scripts/starts/start_error.sh b/scripts/starts/start_error.sh
new file mode 100644
index 00000000..39e807c7
--- /dev/null
+++ b/scripts/starts/start_error.sh
@@ -0,0 +1,12 @@
+
+if [ "$start_old" != "ON" ] && ckcmd journalctl; then
+ 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
+fi
+error=$(cat $TMPDIR/core_test.log | grep -iEo 'error.*=.*|.*ERROR.*|.*FATAL.*')
+logger "服务启动失败!请查看报错信息!详细信息请查看$TMPDIR/core_test.log" 33
+logger "$error" 31
diff --git a/scripts/starts/start_legacy.sh b/scripts/starts/start_legacy.sh
new file mode 100644
index 00000000..f05df7f9
--- /dev/null
+++ b/scripts/starts/start_legacy.sh
@@ -0,0 +1,17 @@
+
+. "$CRASHDIR"/libs/check_cmd.sh
+
+start_legacy(){
+ if ckcmd su && grep -q 'shellcrash:x:0:7890' /etc/passwd;then
+ su shellcrash -c "$1 >/dev/null 2>&1 & echo \$! > /tmp/ShellCrash/$2.pid"
+ elif ckcmd setsid; then
+ setsid $1 >/dev/null 2>&1 &
+ echo $! > "/tmp/ShellCrash/$2.pid"
+ elif ckcmd nohup; then
+ nohup $1 >/dev/null 2>&1 &
+ echo $! > "/tmp/ShellCrash/$2.pid"
+ else
+ $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
new file mode 100644
index 00000000..277fa838
--- /dev/null
+++ b/scripts/starts/start_legacy_wd.sh
@@ -0,0 +1,18 @@
+
+[ -z "$CRASHDIR" ] && CRASHDIR=$( cd $(dirname $0);cd ..;pwd)
+PIDFILE="/tmp/ShellCrash/$1.pid"
+
+if [ -f "$PIDFILE" ]; then
+ PID="$(cat "$PIDFILE")"
+ if [ -n "$PID" ] && kill -0 "$PID" 2>/dev/null; then
+ return 0
+ fi
+fi
+#如果没有进程则拉起
+if [ "$1" = shellcrash ];then
+ "$CRASHDIR"/start.sh start
+else
+ . "$CRASHDIR"/starts/start_legacy.sh
+ start_legacy "$CRASHDIR/menus/bot_tg.sh" "$1"
+fi
+
\ No newline at end of file
diff --git a/scripts/webget.sh b/scripts/webget.sh
deleted file mode 100644
index 477fae30..00000000
--- a/scripts/webget.sh
+++ /dev/null
@@ -1,2623 +0,0 @@
-#!/bin/sh
-# Copyright (C) Juewuy
-
-error_down(){
- echo -e "\033[33m请尝试切换至其他安装源后重新下载!\033[0m"
- echo -e "或者参考 \033[32;4mhttps://juewuy.github.io/bdaz\033[0m 进行本地安装!"
- sleep 1
-}
-dir_avail(){
- df -h >/dev/null 2>&1 && h=$2
- df $h $1 |awk '{ for(i=1;i<=NF;i++){ if(NR==1){ arr[i]=$i; }else{ arr[i]=arr[i]" "$i; } } } END{ for(i=1;i<=NF;i++){ print arr[i]; } }' |grep -E 'Ava|可用' |awk '{print $2}'
- }
-
-#导入订阅、配置文件相关
-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"/start.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" = "未启用" ];then
- echo -e "\033[33m本功能会自动将当前配置文件中的节点域名或IP设置为直连规则以防止出现双重流量!\033[0m"
- echo -e "\033[33m请确保下游设备使用的节点与ShellCrash中使用的节点相同,否则无法生效!\033[0m"
- read -p "启用节点绕过?(1/0) > " res
- [ "$res" = "1" ] && proxies_bypass=已启用
- else
- proxies_bypass=未启用
- 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" = "未启用" ];then
- echo -e "\033[33m本功能会自动将当前配置文件中的节点域名或IP设置为直连规则以防止出现双重流量!\033[0m"
- echo -e "\033[33m请确保下游设备使用的节点与ShellCrash中使用的节点相同,否则无法生效!\033[0m"
- read -p "启用节点绕过?(1/0) > " res
- [ "$res" = "1" ] && proxies_bypass=已启用
- else
- proxies_bypass=未启用
- 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}/start.sh core_check && ${TMPDIR}/CrashCore -t -d ${BINDIR} -f ${TMPDIR}/config.yaml
- if [ "$?" = 0 ];then
- echo -e "\033[32m配置文件生成成功!\033[0m"
- mkdir -p ${CRASHDIR}/yamls
- mv -f ${TMPDIR}/config.yaml ${CRASHDIR}/yamls/config.yaml
- read -p "是否立即启动/重启服务?(1/0) > " res
- [ "$res" = 1 ] && {
- start_core && $CRASHDIR/start.sh 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" > ${TMPDIR}/providers/outbounds.json
- rm -rf ${TMPDIR}/provider_temp_file
- #调用内核测试
- ${CRASHDIR}/start.sh core_check && ${TMPDIR}/CrashCore merge ${TMPDIR}/config.json -C ${TMPDIR}/providers
- if [ "$?" = 0 ];then
- echo -e "\033[32m配置文件生成成功!如果启动超时建议更新里手动安装Singbox-srs数据库常用包!\033[0m"
- mkdir -p ${CRASHDIR}/jsons
- mv -f ${TMPDIR}/config.json ${CRASHDIR}/jsons/config.json
- rm -rf ${TMPDIR}/providers
- read -p "是否立即启动/重启服务?(1/0) > " res
- [ "$res" = 1 ] && {
- start_core && $CRASHDIR/start.sh cronset '更新订阅'
- exit
- }
- else
- echo -e "\033[31m生成配置文件出错,请仔细检查输入!\033[0m"
- rm -rf ${TMPDIR}/CrashCore
- rm -rf ${TMPDIR}/providers
- fi
-}
-setproviders(){ #自定义providers
- #获取模版名称
- 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_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
-}
-
-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'"
-}
-get_core_config(){ #调用工具下载
- ${CRASHDIR}/start.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
- #将用户链接写入配置
- setconfig Https
- setconfig Url "'$Url_link'"
- #获取在线yaml文件
- get_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
- #将用户链接写入配置
- sed -i '/Url=*/'d $CFG_PATH
- setconfig Https "'$link'"
- setconfig Url
- #获取在线yaml文件
- get_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
-}
-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}/task/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
- get_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
-}
-#下载更新相关
-getscripts(){ #更新脚本文件
- ${CRASHDIR}/start.sh 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 -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
-}
-
-getcpucore(){ #自动获取内核架构
- 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
-}
-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
-}
-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
-}
-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 fake-ip #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
- }
- }
- if echo "$crashcore" | grep -q 'singbox';then
- COMMAND='"$TMPDIR/CrashCore run -D $BINDIR -C $TMPDIR/jsons"'
- else
- COMMAND='"$TMPDIR/CrashCore -d $BINDIR -f $TMPDIR/config.yaml"'
- fi
- setconfig COMMAND "$COMMAND" ${CRASHDIR}/configs/command.env && . ${CRASHDIR}/configs/command.env
-}
-getcore(){ #下载内核文件
- [ -z "$crashcore" ] && crashcore=meta
- [ -z "$cpucore" ] && getcpucore
- echo "$crashcore" | grep -q 'singbox' && core_new=singbox || core_new=clash
- #获取在线内核文件
- echo "-----------------------------------------------"
- echo "正在在线获取$crashcore核心文件……"
- if [ -n "$custcorelink" ];then
- zip_type=$(echo $custcorelink | grep -oE 'tar.gz$')
- [ -z "$zip_type" ] && zip_type=$(echo $custcorelink | grep -oE 'gz$')
- if [ -n "$zip_type" ];then
- ${CRASHDIR}/start.sh webget ${TMPDIR}/core_new.${zip_type} "$custcorelink"
- else
- echo -e "\033[31m链接不是以.tar.gz或.gz结尾!下载已取消!\033[0m"
- exit
- fi
- else
- ${CRASHDIR}/start.sh get_bin ${TMPDIR}/core_new.tar.gz bin/${crashcore}/${core_new}-linux-${cpucore}.tar.gz
- fi
- if [ "$?" = "1" ];then
- echo -e "\033[31m核心文件下载失败!\033[0m"
- rm -rf ${TMPDIR}/core_new.tar.gz
- [ -z "$custcorelink" ] && error_down
- else
- [ -n "$(pidof CrashCore)" ] && {
- ${CRASHDIR}/start.sh stop #停止内核服务防止内存不足
- rm -rf "$TMPDIR"/CrashCore #删除缓存内核防止缓存空间不足
- }
- [ -f ${TMPDIR}/core_new.tar.gz ] && {
- mkdir -p ${TMPDIR}/core_tmp
- [ "$BINDIR" = "$TMPDIR" ] && rm -rf ${TMPDIR}/CrashCore #小闪存模式防止空间不足
- tar -zxf "${TMPDIR}/core_new.tar.gz" ${tar_para} -C ${TMPDIR}/core_tmp/
- for file in $(find ${TMPDIR}/core_tmp 2>/dev/null);do
- [ -f $file ] && [ -n "$(echo $file | sed 's#.*/##' | grep -iE '(CrashCore|sing|meta|mihomo|clash|premium)')" ] && mv -f $file ${TMPDIR}/core_new
- done
- rm -rf ${TMPDIR}/core_tmp
- }
- [ -f ${TMPDIR}/core_new.gz ] && gunzip ${TMPDIR}/core_new.gz && rm -rf ${TMPDIR}/core_new.gz
- chmod +x ${TMPDIR}/core_new
- [ "$crashcore" = unknow ] && setcoretype
- if echo "$crashcore" | grep -q 'singbox';then
- core_v=$(${TMPDIR}/core_new version 2>/dev/null | grep version | awk '{print $3}')
- else
- core_v=$(${TMPDIR}/core_new -v 2>/dev/null | head -n 1 | sed 's/ linux.*//;s/.* //')
- fi
- if [ -z "$core_v" ];then
- echo -e "\033[31m核心文件下载成功但校验失败!请尝试手动指定CPU版本\033[0m"
- rm -rf ${TMPDIR}/core_new
- rm -rf ${TMPDIR}/core_new.tar.gz
- setcpucore
- else
- echo -e "\033[32m$crashcore核心下载成功!\033[0m"
- sleep 1
- mv -f ${TMPDIR}/core_new ${TMPDIR}/CrashCore
- if [ -f ${TMPDIR}/core_new.tar.gz ];then
- mv -f ${TMPDIR}/core_new.tar.gz ${BINDIR}/CrashCore.tar.gz
- else
- tar -zcf ${BINDIR}/CrashCore.tar.gz ${tar_para} -C ${TMPDIR} CrashCore
- fi
- setconfig crashcore $crashcore
- setconfig core_v $core_v
- setconfig custcorelink $custcorelink
- switch_core
- fi
- fi
-}
-setcustcore(){ #自定义内核
- checkcustcore(){
- [ "$api_tag" = "latest" ] && api_url=latest || api_url="tags/$api_tag"
- #通过githubapi获取内核信息
- echo -e "\033[32m正在获取内核文件链接!\033[0m"
- ${CRASHDIR}/start.sh 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" ] && getcpucore
- 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[36mMetaCubeX/mihomo\033[32m@alpha\033[0m版本官方内核"
- echo -e "3 \033[36mvernesong/mihomo\033[32m@alpha\033[0m版本内核(支持Smart策略)"
- echo -e "4 \033[36mSagerNet/sing-box\033[32m@release\033[0m版本官方内核"
- echo -e "5 \033[36mreF1nd/sing-box\033[32m@release\033[0m版本内核(完整编译)"
- echo -e "6 \033[36mreF1nd/sing-box\033[32m@dev\033[0m版本内核(完整编译)"
- echo -e "7 Premium-2023.08.17内核(已停止维护)"
- echo -e "a \033[33m自定义内核链接 \033[0m"
- echo "-----------------------------------------------"
- read -p "请输入对应数字 > " num
- case "$num" in
- 1)
- project=MetaCubeX/mihomo
- api_tag=latest
- crashcore=meta
- checkcustcore
- ;;
- 2)
- project=MetaCubeX/mihomo
- api_tag=Prerelease-Alpha
- crashcore=meta
- checkcustcore
- ;;
- 3)
- project=vernesong/mihomo
- api_tag=Prerelease-Alpha
- crashcore=meta
- checkcustcore
- ;;
- 4)
- project=SagerNet/sing-box
- api_tag=latest
- crashcore=singbox
- checkcustcore
- ;;
- 5)
- project=juewuy/ShellCrash
- api_tag=singbox_core_reF1nd
- crashcore=singboxr
- checkcustcore
- ;;
- 6)
- project=juewuy/ShellCrash
- api_tag=singbox_core_dev_reF1nd
- crashcore=singboxr
- checkcustcore
- ;;
- 7)
- project=juewuy/ShellCrash
- api_tag=clash.premium.latest
- crashcore=clashpre
- checkcustcore
- ;;
- a)
- read -p "请输入自定义内核的链接地址(必须是以.tar.gz或.gz结尾的压缩文件) > " link
- [ -n "$link" ] && custcorelink="$link"
- crashcore=unknow
- getcore
- ;;
- *)
- errornum
- ;;
- esac
-}
-setcore(){ #内核选择菜单
- #获取核心及版本信息
- [ -z "$crashcore" ] && crashcore="unknow"
- [ ! -f ${CRASHDIR}/CrashCore.tar.gz -o ! -f ${BINDIR}/CrashCore.tar.gz ] && crashcore="未安装核心"
- echo "$crashcore" | grep -q 'singbox' && core_old=singbox || core_old=clash
- [ -n "$custcorelink" ] && custcore="$(echo $custcorelink | sed 's#.*github.com##; s#/releases/download/#@#; s#-linux.*$##')"
- ###
- echo "-----------------------------------------------"
- [ -z "$cpucore" ] && getcpucore
- 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如需本地上传,请将二进制文件上传至 /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"
- 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"
- 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"
- echo "-----------------------------------------------"
- echo -e "5 \033[36m自定义内核\033[0m $custcore"
- echo -e "6 \033[32m更新当前内核\033[0m"
- echo "-----------------------------------------------"
- echo "9 手动指定处理器架构"
- echo "-----------------------------------------------"
- echo 0 返回上级菜单
- read -p "请输入对应数字 > " num
- case "$num" in
- 0)
- ;;
- 1)
- [ -d "/jffs" ] && {
- echo -e "\033[31mMeta内核使用的GeoSite.dat数据库在华硕设备存在被系统误删的问题,可能无法使用!\033[0m"
- sleep 3
- }
- crashcore=meta
- custcorelink=''
- getcore
- ;;
- 2)
- crashcore=singboxr
- custcorelink=''
- getcore
- ;;
- 3)
- crashcore=singbox
- custcorelink=''
- getcore
- ;;
- 4)
- crashcore=clash
- custcorelink=''
- getcore
- ;;
- 5)
- setcustcore
- setcore
- ;;
- 6)
- getcore
- ;;
- 9)
- setcpucore
- ;;
- *)
- errornum
- ;;
- esac
-}
-
-getgeo(){ #下载Geo文件
- #生成链接
- echo "-----------------------------------------------"
- echo 正在从服务器获取数据库文件…………
- ${CRASHDIR}/start.sh 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
-}
-setcustgeo(){ #下载自定义数据库文件
- getcustgeo(){
- echo "-----------------------------------------------"
- echo "正在获取数据库文件…………"
- ${CRASHDIR}/start.sh 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
- }
- checkcustgeo(){
- [ "$api_tag" = "latest" ] && api_url=latest || api_url="tags/$api_tag"
- [ ! -s ${TMPDIR}/geo.list ] && {
- echo -e "\033[32m正在查找可更新的数据库文件!\033[0m"
- ${CRASHDIR}/start.sh 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
- case "$num" in
- 0)
- ;;
- [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
- custgeolink=https://github.com/${project}/releases/download/${release_tag}/${geotype}
- getcustgeo
- checkcustgeo
- else
- errornum
- fi
- ;;
- *)
- errornum
- ;;
- esac
- else
- echo -e "\033[31m查找失败,请尽量在服务启动后再使用本功能!\033[0m"
- sleep 1
- fi
- }
- 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)
- ;;
- 1)
- project=MetaCubeX/meta-rules-dat
- api_tag=latest
- checkcustgeo
- setcustgeo
- ;;
- 2)
- project=DustinWin/ruleset_geodata
- api_tag=mihomo-geodata
- checkcustgeo
- setcustgeo
- ;;
- 3)
- project=DustinWin/ruleset_geodata
- api_tag=sing-box-ruleset
- checkcustgeo
- setcustgeo
- ;;
- 4)
- project=DustinWin/ruleset_geodata
- api_tag=mihomo-ruleset
- checkcustgeo
- setcustgeo
- ;;
- 5)
- project=Loyalsoldier/geoip
- api_tag=latest
- checkcustgeo
- setcustgeo
- ;;
- 9)
- read -p "请输入自定义数据库的链接地址 > " link
- [ -n "$link" ] && custgeolink="$link"
- getgeo
- setcustgeo
- ;;
- *)
- errornum
- ;;
- esac
-}
-setgeo(){ #数据库选择菜单
- . $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 -e " 5 Mihomo-mrs数据库常用包(约1mb) \033[33m$mrs_v\033[0m"
- echo "-----------------------------------------------"
- echo -e " 6 Singbox-srs数据库常用包(约0.8mb) \033[33m$srs_v\033[0m"
- 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)
- ;;
- 1)
- geotype=china_ip_list.txt
- geoname=cn_ip.txt
- getgeo
- setgeo
- ;;
- 2)
- geotype=china_ipv6_list.txt
- geoname=cn_ipv6.txt
- getgeo
- setgeo
- ;;
- 3)
- geotype=cn_mini.mmdb
- geoname=Country.mmdb
- getgeo
- setgeo
- ;;
- 4)
- geotype=geosite.dat
- geoname=GeoSite.dat
- getgeo
- setgeo
- ;;
- 5)
- geotype=mrs.tar.gz
- geoname=mrs.tar.gz
- getgeo
- setgeo
- ;;
- 6)
- geotype=srs.tar.gz
- geoname=srs.tar.gz
- getgeo
- setgeo
- ;;
- 8)
- setcustgeo
- setgeo
- ;;
- 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
- }
- setgeo
- ;;
- *)
- errornum
- ;;
-esac
-}
-
-getdb(){ #下载Dashboard文件
- dblink="${update_url}/"
- echo "-----------------------------------------------"
- echo 正在连接服务器获取安装文件…………
- ${CRASHDIR}/start.sh get_bin ${TMPDIR}/clashdb.tar.gz bin/dashboard/${db_type}.tar.gz
- if [ "$?" = "1" ];then
- echo "-----------------------------------------------"
- echo -e "\033[31m文件下载失败!\033[0m"
- echo "-----------------------------------------------"
- error_down
- setdb
- 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
- #修改默认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
- elif [ "$db_type" = "meta_xd" ];then
- 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
- fi
- #写入配置文件
- setconfig hostdir "'$hostdir'"
- echo "-----------------------------------------------"
- echo -e "\033[32m面板安装成功!\033[36m如未生效,请使用【Ctrl+F5】强制刷新浏览器!!!\033[0m"
- rm -rf ${TMPDIR}/clashdb.tar.gz
- fi
- sleep 1
-}
-setdb(){
- 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 [ "$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
- setdb
- echo -e "\033[33m安装已取消!\033[0m"
- 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
-
- if [ "$num" = '1' ]; then
- dbdir=${CRASHDIR}/ui
- hostdir=":$db_port/ui"
- getdb
- elif [ "$num" = '2' ]; then
- dbdir=/www/clash
- hostdir='/clash'
- getdb
- else
- setdb
- echo -e "\033[33m安装已取消!\033[0m"
- fi
- else
- dbdir=${CRASHDIR}/ui
- hostdir=":$db_port/ui"
- getdb
- fi
- }
-
- 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
-
- case "$num" in
- 0) ;;
- 1)
- db_type=zashboard
- echo $update_url
- setconfig external_ui_url "https://github.com/Zephyruso/zashboard/releases/latest/download/dist-cdn-fonts.zip"
- dbdir
- ;;
- 2)
- db_type=meta_xd
- setconfig external_ui_url "https://raw.githubusercontent.com/juewuy/ShellCrash/update/bin/dashboard/meta_xd.tar.gz"
- dbdir
- ;;
- 3)
- db_type=meta_yacd
- dbdir
- ;;
- 4)
- db_type=clashdb
- dbdir
- ;;
- 5)
- db_type=meta_db
- dbdir
- ;;
- 6)
- db_type=yacd
- 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
- ;;
- *)
- errornum
- ;;
- esac
-}
-
-getcrt(){ #下载根证书文件
- echo "-----------------------------------------------"
- echo "正在连接服务器获取安装文件…………"
- ${CRASHDIR}/start.sh 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
- ${CRASHDIR}/start.sh 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
-}
-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
-}
-#安装源
-setserver(){
- [ -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
- saveserver(){
- #写入配置文件
- setconfig update_url "'$update_url'"
- setconfig url_id $url_id
- setconfig release_type $release_type
- echo "-----------------------------------------------"
- echo -e "\033[32m源地址切换成功!\033[0m"
- }
- 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
- ;;
- [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
- setserver
- 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
- else
- url_id=$url_id_new
- update_url=''
- saveserver
- fi
- unset url_id_new
- ;;
- a)
- release_type=stable
- [ -z "$url_id" ] && url_id=101
- saveserver
- setserver
- ;;
- b)
- release_type=master
- [ -z "$url_id" ] && url_id=101
- saveserver
- setserver
- ;;
- 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
- setserver
- ;;
- 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}/start.sh get_bin ${TMPDIR}/release_version bin/release_version
- if [ "$?" = "0" ];then
- echo -e "\033[31m请选择想要回退至的稳定版版本:\033[0m"
- cat ${TMPDIR}/release_version | awk '{print " "NR" "$1}'
- echo -e " 0 返回上级菜单"
- read -p "请输入对应数字 > " num
- if [ -z "$num" -o "$num" = 0 ]; then
- setserver
- elif [ $num -le $(cat ${TMPDIR}/release_version 2>/dev/null | awk 'END{print NR}') ]; then
- release_type=$(cat ${TMPDIR}/release_version | awk '{print $1}' | sed -n "$num"p)
- update_url=''
- saveserver
- else
- echo "-----------------------------------------------"
- errornum
- sleep 1
- setserver
- fi
- else
- echo "-----------------------------------------------"
- echo -e "\033[31m版本回退信息获取失败,请尝试更换其他安装源!\033[0m"
- sleep 1
- setserver
- fi
- rm -rf ${TMPDIR}/release_version
- else
- echo -e "\033[31m当前源不支持版本回退,请尝试更换其他安装源!\033[0m"
- sleep 1
- setserver
- fi
- ;;
- *)
- errornum
- ;;
- esac
-}
-#检查更新
-checkupdate(){
- ${CRASHDIR}/start.sh get_bin ${TMPDIR}/version_new version echooff
- [ "$?" = "0" ] && {
- version_new=$(cat ${TMPDIR}/version_new)
- ${CRASHDIR}/start.sh 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
-}
-update(){
- echo "-----------------------------------------------"
- echo -ne "\033[32m正在检查更新!\033[0m\r"
- checkupdate
- [ -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"
- [ "$(dir_avail ${CRASHDIR})" -le 5120 ] && [ "$CRASHDIR" = "$BINDIR" ] && {
- echo -e "\033[33m当前目录剩余空间较低,建议开启小闪存模式!\033[0m"
- sleep 1
- }
- 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
- case "$num" in
- 0)
- ;;
- 1)
- setscripts
- ;;
- 2)
- setcore
- ;;
- 3)
- setgeo
- update
- ;;
- 4)
- setdb
- update
- ;;
- 5)
- setcrt
- update
- ;;
- 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
- update
- ;;
- 7)
- setserver
- update
- ;;
- 8)
- . ${CRASHDIR}/task/task.sh && task_add
- update
- ;;
- 9)
- uninstall
- exit
- ;;
- 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 "-----------------------------------------------"
- sleep 2
- update
- ;;
- *)
- errornum
- ;;
- esac
-}
-#新手引导
-userguide(){
-
- 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
- }
- setconfig crashcore "meta"
- setconfig redir_mod "$redir_mod"
- setconfig dns_mod mix
- setconfig firewall_area '1'
- #默认启用绕过CN-IP
- setconfig cn_ip_route 已开启
- #自动识别IPV6
- [ -n "$(ip a 2>&1 | grep -w 'inet6' | grep -E 'global' | sed 's/.*inet6.//g' | sed 's/scope.*$//g')" ] && {
- setconfig ipv6_redir 已开启
- setconfig ipv6_support 已开启
- setconfig ipv6_dns 已开启
- setconfig cn_ipv6_route 已开启
- }
- #设置开机启动
- [ -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 "未开启"
- 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
- #检测及下载根证书
- openssldir="$(openssl version -d 2>&1 | awk -F '"' '{print $2}')"
- [ ! -d "$openssldir/certs" ] && openssldir=/etc/ssl
- if [ -d $openssldir/certs -a ! -f $openssldir/certs/ca-certificates.crt ];then
- echo "-----------------------------------------------"
- echo -e "\033[33m当前设备未找到根证书文件\033[0m"
- echo "-----------------------------------------------"
- read -p "是否下载并安装根证书?(1/0) > " res
- [ "$res" = 1 ] && checkupdate && getcrt
- fi
- #设置加密DNS
- if [ -s $openssldir/certs/ca-certificates.crt ];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'"
- fi
- #开启公网访问
- sethost(){
- read -p "请输入你的公网IP地址 > " host
- echo $host | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
- if [ -z "$host" ];then
- echo -e "\033[31m请输入正确的IP地址!\033[0m"
- sethost
- fi
- }
- if ckcmd systemctl;then
- echo "-----------------------------------------------"
- echo -e "\033[32m是否开启公网访问Dashboard面板及socks服务?\033[0m"
- echo -e "注意当前设备必须有公网IP才能从公网正常访问"
- echo -e "\033[31m此功能会增加暴露风险请谨慎使用!\033[0m"
- echo -e "vps设备可能还需要额外在服务商后台开启相关端口"
- read -p "现在开启?(1/0) > " res
- if [ "$res" = 1 ];then
- read -p "请先设置面板访问秘钥 > " secret
- read -p "请先修改Socks服务端口(1-65535) > " mix_port
- read -p "请先设置Socks服务密码(账号默认为crash) > " sec
- [ -z "$sec" ] && authentication=crash:$sec
- host=$(curl ip.sb 2>/dev/null | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
- if [ -z "$host" ];then
- sethost
- fi
- public_support=已开启
- setconfig secret $secret
- setconfig mix_port $mix_port
- setconfig host $host
- setconfig public_support $public_support
- setconfig authentication "'$authentication'"
- fi
- fi
- #启用推荐的自动任务配置
- . ${CRASHDIR}/task/task.sh && task_recom
- #小米设备软固化
- if [ "$systype" = "mi_snapshot" ];then
- echo "-----------------------------------------------"
- echo -e "\033[33m检测到为小米路由设备,启用软固化可防止路由升级后丢失SSH\033[0m"
- read -p "是否启用软固化功能?(1/0) > " res
- [ "$res" = 1 ] && 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 && {
- if [ -f "$CRASHDIR"/v2b_api.sh ];then
- . "$CRASHDIR"/v2b_api.sh
- else
- set_core_config
- fi
- set_core_config
- inuserguide=""
- }
- }
- #回到主界面
- echo "-----------------------------------------------"
- echo -e "\033[36m很好!现在只需要执行启动就可以愉快的使用了!\033[0m"
- echo "-----------------------------------------------"
- read -p "立即启动服务?(1/0) > " res
- [ "$res" = 1 ] && start_core && sleep 2
- main_menu
-}
-#测试菜单
-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}/start.sh core_check && $TMPDIR/CrashCore merge $TMPDIR/debug.json -C $TMPDIR/jsons && echo -e "\033[32m合并成功!\033[0m"
- rm -rf ${TMPDIR}/CrashCore
- main_menu
- ;;
- *)
- errornum
- ;;
- esac
-}
-testcommand(){
- echo "$crashcore" | grep -q 'singbox' && config_path=${JSONSDIR}/config.json || config_path=${YAMLSDIR}/config.yaml
- 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
- else
- [ "$firewall_area" = 1 -o "$firewall_area" = 3 -o "$firewall_area" = 5 -o "$vm_redir" = "已开启" ] && {
- 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" = "已开启" ] && {
- [ "$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" = "已开启" ] && {
- echo "-------------vm-Redir-------------------"
- iptables -t nat -L shellcrash_vm --line-numbers
- iptables -t nat -L shellcrash_vm_dns --line-numbers
- }
- fi
- exit;
- ;;
- 5)
- 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
-}
-
-case "$1" in
- *)
- $1
- ;;
-esac
diff --git a/version b/version
index 0a1c28f1..ee59bfe2 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-1.9.3release
+1.9.4beta1