mirror of
https://github.com/juewuy/ShellCrash.git
synced 2026-10-24 11:49:20 +00:00
Compare commits
36
Commits
master
...
b6e4c629c5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6e4c629c5 | ||
|
|
87d2be57a4 | ||
|
|
529d16fa75 | ||
|
|
783453aabf | ||
|
|
5599b05671 | ||
|
|
f97d10de30 | ||
|
|
0ac044e5c0 | ||
|
|
eae1a268b2 | ||
|
|
3b07d419f0 | ||
|
|
8d6ffdc3c9 | ||
|
|
8172c3b35d | ||
|
|
b4eb924653 | ||
|
|
7448862297 | ||
|
|
cec5d15158 | ||
|
|
f222070bf9 | ||
|
|
436d3db976 | ||
|
|
2176f5dc10 | ||
|
|
49e48b7f13 | ||
|
|
bfacd2a018 | ||
|
|
3f3eb9d231 | ||
|
|
88eb7efd8a | ||
|
|
88b1a633d7 | ||
|
|
2ecd389afe | ||
|
|
585fdd9ae7 | ||
|
|
6951f24696 | ||
|
|
de1d9e20f7 | ||
|
|
df9ae2a8d8 | ||
|
|
b255ac47f4 | ||
|
|
a42f988a6e | ||
|
|
ed18140af6 | ||
|
|
376197c654 | ||
|
|
d37267bceb | ||
|
|
d4d74e5d3f | ||
|
|
a510bc2ffd | ||
|
|
6614a7dcaf | ||
|
|
f9e2076976 |
@@ -83,12 +83,24 @@ jobs:
|
|||||||
|
|
||||||
- name: get sing-box version
|
- name: get sing-box version
|
||||||
id: sing-box
|
id: sing-box
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
git remote add sekai https://github.com/SagerNet/sing-box.git
|
if [ "$REPO" = 'SagerNet/sing-box' ]; then
|
||||||
git fetch --tags sekai
|
version=$(gh api --paginate "repos/${REPO}/tags?per_page=100" --jq '.[].name' \
|
||||||
version=$(CGO_ENABLED=0 go run ./cmd/internal/read_tag)
|
| sort -V \
|
||||||
[ -z "$version" ] && version=${{ inputs.tag2 }}
|
| tail -n 1) || true
|
||||||
version=$(echo ${version%-*})
|
elif [ "$REPO" = 'reF1nd/sing-box' ]; then
|
||||||
|
version=$(gh api --paginate "repos/${REPO}/tags?per_page=100" --jq '.[].name' \
|
||||||
|
| grep -F 'reF1nd' \
|
||||||
|
| sort -V \
|
||||||
|
| tail -n 1) || true
|
||||||
|
else
|
||||||
|
version=''
|
||||||
|
fi
|
||||||
|
if [ -z "$version" ]; then
|
||||||
|
version='${{ inputs.tag2 }}'
|
||||||
|
fi
|
||||||
echo version=$version >> $GITHUB_OUTPUT
|
echo version=$version >> $GITHUB_OUTPUT
|
||||||
if [ -z "$TAGS" ];then
|
if [ -z "$TAGS" ];then
|
||||||
if [ "$REPO" = 'SagerNet/sing-box' ];then
|
if [ "$REPO" = 'SagerNet/sing-box' ];then
|
||||||
|
|||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
# Operating system files
|
||||||
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
Thumbs.db
|
||||||
|
Desktop.ini
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
*.stackdump
|
||||||
|
|
||||||
|
# Editor temporary files
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
.#*
|
||||||
|
|
||||||
|
# Workflow temporary files
|
||||||
|
bin/dashboard/.tmp/
|
||||||
|
|
||||||
|
#Others
|
||||||
|
/一键同步.bat
|
||||||
|
/一键打包.bash
|
||||||
|
/刷新CDN.bash
|
||||||
|
/一键同步列表.scp
|
||||||
|
/v2b_api.sh
|
||||||
|
/login.sh
|
||||||
|
/tools/login.sh
|
||||||
|
/tools/v2b_api.sh
|
||||||
|
tools
|
||||||
|
/检出dev.bash
|
||||||
|
/list.scp
|
||||||
|
/.codex
|
||||||
@@ -74,7 +74,10 @@ COPY --from=builder /tmp/s6_noarch.tar.xz /tmp/s6_noarch.tar.xz
|
|||||||
RUN tar -xJf /tmp/s6_noarch.tar.xz -C / && rm -rf /tmp/s6_noarch.tar.xz
|
RUN tar -xJf /tmp/s6_noarch.tar.xz -C / && rm -rf /tmp/s6_noarch.tar.xz
|
||||||
RUN tar -xJf /tmp/s6_arch.tar.xz -C / && rm -rf /tmp/s6_arch.tar.xz
|
RUN tar -xJf /tmp/s6_arch.tar.xz -C / && rm -rf /tmp/s6_arch.tar.xz
|
||||||
COPY docker/s6-rc.d /etc/s6-overlay/s6-rc.d
|
COPY docker/s6-rc.d /etc/s6-overlay/s6-rc.d
|
||||||
|
COPY docker/s6-overlay/scripts/sync-autostart /etc/s6-overlay/scripts/sync-autostart
|
||||||
|
RUN chmod +x /etc/s6-overlay/scripts/sync-autostart
|
||||||
ENV S6_CMD_WAIT_FOR_SERVICES=1
|
ENV S6_CMD_WAIT_FOR_SERVICES=1
|
||||||
|
ENV S6_STAGE2_HOOK=/etc/s6-overlay/scripts/sync-autostart
|
||||||
|
|
||||||
ENTRYPOINT ["/init"]
|
ENTRYPOINT ["/init"]
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
meta_v=v1.19.17
|
meta_v=v1.19.17
|
||||||
singboxr_v=1.13.0-alpha.27
|
singboxr_v=1.13.0-alpha.27
|
||||||
versionsh=1.9.5beta4
|
versionsh=1.9.6alpha1
|
||||||
GeoIP_v=20251205
|
GeoIP_v=20251205
|
||||||
|
|||||||
+3
-1
@@ -89,6 +89,8 @@ mkdir -p /root/ShellCrash
|
|||||||
docker run -d \
|
docker run -d \
|
||||||
………………
|
………………
|
||||||
-v shellcrash_configs:/etc/ShellCrash/configs \
|
-v shellcrash_configs:/etc/ShellCrash/configs \
|
||||||
|
-v shellcrash_yamls:/etc/ShellCrash/yamls \
|
||||||
|
-v shellcrash_jsons:/etc/ShellCrash/jsons \
|
||||||
………………
|
………………
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -134,7 +136,7 @@ docker rm -f shellcrash
|
|||||||
### Docker删除卷
|
### Docker删除卷
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
docker volume rm shellcrash_configs
|
docker volume rm shellcrash_configs shellcrash_yamls shellcrash_jsons
|
||||||
```
|
```
|
||||||
|
|
||||||
### Compose删除容器&卷
|
### Compose删除容器&卷
|
||||||
|
|||||||
@@ -18,10 +18,14 @@ services:
|
|||||||
# - net.ipv6.conf.all.forwarding=1
|
# - net.ipv6.conf.all.forwarding=1
|
||||||
volumes:
|
volumes:
|
||||||
- shellcrash_configs:/etc/ShellCrash/configs:rw
|
- shellcrash_configs:/etc/ShellCrash/configs:rw
|
||||||
|
- shellcrash_yamls:/etc/ShellCrash/yamls:rw
|
||||||
|
- shellcrash_jsons:/etc/ShellCrash/jsons:rw
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
shellcrash_configs:
|
shellcrash_configs:
|
||||||
|
shellcrash_yamls:
|
||||||
|
shellcrash_jsons:
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
macvlan_lan:
|
macvlan_lan:
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# 在 s6-rc 编译 user bundle 之前,把 configs 卷中的自启状态同步到 contents.d
|
||||||
|
# 由 S6_STAGE2_HOOK 调用;删除重建容器后仍可按 volume 恢复开机自启
|
||||||
|
|
||||||
|
CRASHDIR=/etc/ShellCrash
|
||||||
|
CFG_MARK="$CRASHDIR/configs/.autostart"
|
||||||
|
S6_MARK=/etc/s6-overlay/s6-rc.d/user/contents.d/afstart
|
||||||
|
|
||||||
|
mkdir -p "$CRASHDIR/configs" /etc/s6-overlay/s6-rc.d/user/contents.d
|
||||||
|
|
||||||
|
# 兼容旧容器:仅有 s6 标记时迁移到 configs
|
||||||
|
if [ -f "$S6_MARK" ] && [ ! -f "$CFG_MARK" ]; then
|
||||||
|
touch "$CFG_MARK"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$CFG_MARK" ] && [ ! -f "$CRASHDIR/.dis_startup" ]; then
|
||||||
|
touch "$S6_MARK"
|
||||||
|
else
|
||||||
|
rm -f "$S6_MARK"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#LAN域名 - 局域网常见域名后缀
|
||||||
|
*.lan
|
||||||
|
*.local
|
||||||
|
*.localdomain
|
||||||
|
*.home
|
||||||
|
*.internal
|
||||||
|
*.home.arpa
|
||||||
|
*.localnet
|
||||||
|
|
||||||
|
#私有网络域名示例
|
||||||
|
router.lan
|
||||||
|
nas.lan
|
||||||
|
*.home.lan
|
||||||
@@ -11,7 +11,7 @@ proxy-groups:
|
|||||||
- {name: 🚀 节点选择, type: select, proxies: [♻️ 自动选择, ✨ 自动选择(去高倍率), 🛠️ 手动切换, ⚖️ 负载均衡, 🚑 故障转移, 🎯 本地直连, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
|
- {name: 🚀 节点选择, type: select, proxies: [♻️ 自动选择, ✨ 自动选择(去高倍率), 🛠️ 手动切换, ⚖️ 负载均衡, 🚑 故障转移, 🎯 本地直连, 🇭🇰 香港节点, 🇹🇼 台湾节点, 🇺🇸 美国节点, 🇯🇵 日本节点, 🇪🇺 欧洲节点, 🇰🇷 韩国节点, 🇸🇬 狮城节点, 👑 高级节点, 📉 省流节点, {providers_tags}]}
|
||||||
- {name: 🛠️ 手动切换, type: select, include-all: true, 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)"}
|
||||||
- {name: ✨ 自动选择(去高倍率), type: url-test, interval: 1800, tolerance: 50, include-all: true, exclude-filter: "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www)`(?i)(专线|专用|高级|直连|急速|高速|高倍率|游戏|铂金|钻石|企业|VIP|Ultra|Game|IEPL|IPLC|AIA|BGP|GIA|CN2|CMI|HGC|HKT|CTM|CC|AC|x([2-9]|\\d{2,}))"}
|
- {name: ✨ 自动选择(去高倍率), type: url-test, interval: 1800, tolerance: 50, include-all: true, exclude-filter: "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www)`(?i)(专线|专用|高级|直连|急速|高速|高倍率|游戏|铂金|钻石|企业|VIP|Ultra|Game|IEPL|IPLC|AIA|BGP|GIA|CN2|CMI|HGC|HKT|CTM|CC|AC|(x([2-9]|[1-9][0-9]+)|([2-9]|[1-9][0-9]+)x))"}
|
||||||
- {name: ⚖️ 负载均衡, type: load-balance, interval: 1800, include-all: true, hidden: true, exclude-filter: "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www)"}
|
- {name: ⚖️ 负载均衡, type: load-balance, interval: 1800, include-all: true, hidden: true, exclude-filter: "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www)"}
|
||||||
- {name: 🚑 故障转移, type: fallback, interval: 1800, include-all: true, hidden: true, exclude-filter: "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www)"}
|
- {name: 🚑 故障转移, type: fallback, interval: 1800, include-all: true, hidden: true, exclude-filter: "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www)"}
|
||||||
#
|
#
|
||||||
@@ -51,7 +51,7 @@ proxy-groups:
|
|||||||
- {name: 🇰🇷 韩国节点, type: url-test, interval: 120, tolerance: 50, include-all: true, filter: "(?i)(🇰🇷|韩|韓|首尔|kr|kor)"}
|
- {name: 🇰🇷 韩国节点, type: url-test, interval: 120, tolerance: 50, include-all: true, filter: "(?i)(🇰🇷|韩|韓|首尔|kr|kor)"}
|
||||||
- {name: 🇸🇬 狮城节点, type: url-test, interval: 120, tolerance: 50, include-all: true, filter: "(?i)(🇸🇬|新加坡|狮城|sg|singapore)"}
|
- {name: 🇸🇬 狮城节点, type: url-test, interval: 120, tolerance: 50, include-all: true, filter: "(?i)(🇸🇬|新加坡|狮城|sg|singapore)"}
|
||||||
|
|
||||||
- {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)(专线|专用|高级|直连|急速|高速|高倍率|游戏|铂金|钻石|企业|VIP|Ultra|Game|IEPL|IPLC|AIA|BGP|GIA|CN2|CMI|HGC|HKT|CTM|CC|AC|(x([2-9]|[1-9][0-9]+)|([2-9]|[1-9][0-9]+)x))"}
|
||||||
- {name: 📉 省流节点, type: url-test, interval: 1800, tolerance: 50, include-all: true, filter: "(?i)(0\\.[1-6]|低倍率|省流|大流量|公益|免费|闲时|Low)"}
|
- {name: 📉 省流节点, type: url-test, interval: 1800, tolerance: 50, include-all: true, filter: "(?i)(0\\.[1-6]|低倍率|省流|大流量|公益|免费|闲时|Low)"}
|
||||||
|
|
||||||
#规则提供者(更新mrs格式)
|
#规则提供者(更新mrs格式)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
{ "tag": "🚀 节点选择", "type": "selector", "outbounds": ["♻️ 自动选择", "✨ 自动选择(去高倍率)", "🛠️ 手动切换", "🎯 本地直连", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
|
{ "tag": "🚀 节点选择", "type": "selector", "outbounds": ["♻️ 自动选择", "✨ 自动选择(去高倍率)", "🛠️ 手动切换", "🎯 本地直连", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
|
||||||
{ "tag": "🛠️ 手动切换", "type": "selector", "use_all_providers": true, "outbounds": ["🎯 本地直连", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
|
{ "tag": "🛠️ 手动切换", "type": "selector", "use_all_providers": true, "outbounds": ["🎯 本地直连", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
|
||||||
{ "tag": "♻️ 自动选择", "type": "urltest", "interval": "2m", "use_all_providers": true, "exclude": "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www)" },
|
{ "tag": "♻️ 自动选择", "type": "urltest", "interval": "2m", "use_all_providers": true, "exclude": "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www)" },
|
||||||
{ "tag": "✨ 自动选择(去高倍率)", "type": "urltest", "interval": "2m", "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": "✨ 自动选择(去高倍率)", "type": "urltest", "interval": "2m", "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]|[1-9][0-9]+)|([2-9]|[1-9][0-9]+)x))" },
|
||||||
|
|
||||||
{ "tag": "🤖 AI 平台", "type": "selector", "outbounds": ["🚀 节点选择", "🤖 AI节点(过滤港澳)", "🎯 本地直连", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
|
{ "tag": "🤖 AI 平台", "type": "selector", "outbounds": ["🚀 节点选择", "🤖 AI节点(过滤港澳)", "🎯 本地直连", "♻️ 自动选择", "🛠️ 手动切换", "🇭🇰 香港节点", "🇹🇼 台湾节点", "🇺🇸 美国节点", "🇯🇵 日本节点", "🇪🇺 欧洲节点", "🇰🇷 韩国节点", "🇸🇬 狮城节点", "👑 高级节点", "📉 省流节点", {providers_tags}] },
|
||||||
{ "tag": "🤖 AI节点(过滤港澳)", "type": "urltest", "interval": "2m", "use_all_providers": true, "exclude": "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www|🇭🇰|港|🇲🇴|澳门|hk|hongkong|hong kong)" },
|
{ "tag": "🤖 AI节点(过滤港澳)", "type": "urltest", "interval": "2m", "use_all_providers": true, "exclude": "(?i)(剩余|重置|到期|防失联|官网|导航|客服|http|www|🇭🇰|港|🇲🇴|澳门|hk|hongkong|hong kong)" },
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
{ "tag": "🇰🇷 韩国节点", "type": "urltest", "interval": "2m", "use_all_providers": true, "include": "(?i)(🇰🇷|韩|韓|首尔|kr|kor)" },
|
{ "tag": "🇰🇷 韩国节点", "type": "urltest", "interval": "2m", "use_all_providers": true, "include": "(?i)(🇰🇷|韩|韓|首尔|kr|kor)" },
|
||||||
{ "tag": "🇸🇬 狮城节点", "type": "urltest", "interval": "2m", "use_all_providers": true, "include": "(?i)(🇸🇬|新加坡|狮城|sg|singapore)" },
|
{ "tag": "🇸🇬 狮城节点", "type": "urltest", "interval": "2m", "use_all_providers": true, "include": "(?i)(🇸🇬|新加坡|狮城|sg|singapore)" },
|
||||||
|
|
||||||
{ "tag": "👑 高级节点", "type": "urltest", "interval": "2m", "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", "interval": "2m", "use_all_providers": true, "include": "(?i)(专线|专用|高级|直连|急速|高速|高倍率|游戏|铂金|钻石|企业|VIP|Ultra|Game|IEPL|IPLC|AIA|BGP|GIA|CN2|CMI|HGC|HKT|CTM|CC|AC|(x([2-9]|[1-9][0-9]+)|([2-9]|[1-9][0-9]+)x))" },
|
||||||
{ "tag": "📉 省流节点", "type": "urltest", "interval": "2m", "use_all_providers": true, "include": "(?i)(0[.][1-5]|低倍率|省流|大流量|公益|免费|闲时|Low)" }
|
{ "tag": "📉 省流节点", "type": "urltest", "interval": "2m", "use_all_providers": true, "include": "(?i)(0[.][1-5]|低倍率|省流|大流量|公益|免费|闲时|Low)" }
|
||||||
],
|
],
|
||||||
"route": {
|
"route": {
|
||||||
|
|||||||
+1
-1
@@ -77,7 +77,7 @@ rm -rf "$CRASHDIR"/starts/shellcrash.openrc
|
|||||||
command -v bash >/dev/null 2>&1 && shtype=bash
|
command -v bash >/dev/null 2>&1 && shtype=bash
|
||||||
[ -x /bin/ash ] && shtype=ash
|
[ -x /bin/ash ] && shtype=ash
|
||||||
#批量授权
|
#批量授权
|
||||||
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
|
for file in start.sh starts/bfstart.sh starts/afstart.sh starts/fw_stop.sh starts/fw_ipv6_watch.sh menu.sh menus/task_cmd.sh menus/bot_tg.sh; do
|
||||||
sed -i "s|/bin/sh|/bin/$shtype|" "$CRASHDIR/$file" 2>/dev/null
|
sed -i "s|/bin/sh|/bin/$shtype|" "$CRASHDIR/$file" 2>/dev/null
|
||||||
chmod +x "$CRASHDIR/$file" 2>/dev/null
|
chmod +x "$CRASHDIR/$file" 2>/dev/null
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ SET_MENU_SKIP_CERT="跳过证书验证:"
|
|||||||
SET_MENU_SNIFFER="启用域名嗅探:"
|
SET_MENU_SNIFFER="启用域名嗅探:"
|
||||||
SET_MENU_ADV_PORT="自定义端口及密钥"
|
SET_MENU_ADV_PORT="自定义端口及密钥"
|
||||||
SET_MENU_IPV6="IPv6设置: "
|
SET_MENU_IPV6="IPv6设置: "
|
||||||
|
SET_MENU_UDP_BUFFER="提高UDP缓冲上限(16 MiB):"
|
||||||
SET_MENU_RESET="重置/备份/还原脚本设置"
|
SET_MENU_RESET="重置/备份/还原脚本设置"
|
||||||
SET_MENU_LANG="多语言切换"
|
SET_MENU_LANG="多语言切换"
|
||||||
SET_MENU_UI="UI切换"
|
SET_MENU_UI="UI切换"
|
||||||
@@ -26,6 +27,9 @@ SET_SNIFFER_LOCKED="当前内核与DNS模式组合下,域名嗅探无法关闭
|
|||||||
|
|
||||||
SET_CORE_RUNNING="检测到服务正在运行,需要先停止服务!"
|
SET_CORE_RUNNING="检测到服务正在运行,需要先停止服务!"
|
||||||
SET_CORE_STOP_CONFIRM="是否确认停止服务?"
|
SET_CORE_STOP_CONFIRM="是否确认停止服务?"
|
||||||
|
SET_UDP_BUFFER_ON="已启用UDP缓冲上限优化!"
|
||||||
|
SET_UDP_BUFFER_OFF="已禁用UDP缓冲上限优化,现有系统值不会被降低。"
|
||||||
|
SET_UDP_BUFFER_RESTART="重启服务后对新连接生效。"
|
||||||
|
|
||||||
# =================================================
|
# =================================================
|
||||||
# Backup / Restore / Reset
|
# Backup / Restore / Reset
|
||||||
|
|||||||
@@ -65,3 +65,21 @@ DNS_ADD_FAIL="添加失败"
|
|||||||
DNS_NOW="当前DNS:"
|
DNS_NOW="当前DNS:"
|
||||||
DNS_INPUT_NEW="请直接输入新的DNS地址"
|
DNS_INPUT_NEW="请直接输入新的DNS地址"
|
||||||
DNS_INPUT_RESET="或输入 r 重置DNS地址"
|
DNS_INPUT_RESET="或输入 r 重置DNS地址"
|
||||||
|
|
||||||
|
#=====直连域名=====
|
||||||
|
DNS_DIRECT_MENU="管理直连域名列表"
|
||||||
|
DNS_DIRECT_DESC="用于在 mix/route 模式下指定特定域名使用直连 DNS 解析"
|
||||||
|
DNS_DIRECT_TIP="适用于局域网域名、内网服务域名等需要本地 DNS 解析的场景"
|
||||||
|
DNS_DIRECT_EXAMPLE="示例格式:\n*.lan\n*.local\nnas.home"
|
||||||
|
DNS_DIRECT_EXIST="已添加的直连域名:"
|
||||||
|
DNS_DIRECT_EMPTY="当前尚未添加任何自定义直连域名"
|
||||||
|
DNS_DIRECT_EDIT="输入序号删除,输入 a 添加域名,输入 r 加载预设,输入 t 测试域名"
|
||||||
|
DNS_DIRECT_ADD_LAN="添加局域网域名"
|
||||||
|
DNS_DIRECT_LOAD_PRESET="加载预设局域网域名列表"
|
||||||
|
DNS_DIRECT_LOAD_OK="已加载预设局域网域名列表"
|
||||||
|
DNS_DIRECT_INPUT_HINT="请输入需要直连解析的域名(支持通配符 *.lan)"
|
||||||
|
DNS_DIRECT_TEST="测试域名解析"
|
||||||
|
DNS_DIRECT_TEST_INPUT="请输入要测试的域名"
|
||||||
|
DNS_DIRECT_TEST_RESULT="解析结果:"
|
||||||
|
DNS_DIRECT_TEST_IN_LIST="✓ 该域名已配置为直连解析"
|
||||||
|
DNS_DIRECT_TEST_NOT_IN_LIST="✗ 该域名未在直连列表中"
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ SET_MENU_SKIP_CERT="Skip Cert Verify:"
|
|||||||
SET_MENU_SNIFFER="Enable Sniff:"
|
SET_MENU_SNIFFER="Enable Sniff:"
|
||||||
SET_MENU_ADV_PORT="Custom Ports and Secrets"
|
SET_MENU_ADV_PORT="Custom Ports and Secrets"
|
||||||
SET_MENU_IPV6="IPv6 Settings:"
|
SET_MENU_IPV6="IPv6 Settings:"
|
||||||
|
SET_MENU_UDP_BUFFER="Raise UDP Buffer Limit (16 MiB):"
|
||||||
SET_MENU_RESET="Reset / Backup / Restore Script Settings"
|
SET_MENU_RESET="Reset / Backup / Restore Script Settings"
|
||||||
SET_MENU_LANG="Language"
|
SET_MENU_LANG="Language"
|
||||||
SET_MENU_UI="UI Switch"
|
SET_MENU_UI="UI Switch"
|
||||||
@@ -26,6 +27,9 @@ SET_SNIFFER_LOCKED="Domain sniffing cannot be disabled with the current core and
|
|||||||
|
|
||||||
SET_CORE_RUNNING="Service is currently running and must be stopped first!"
|
SET_CORE_RUNNING="Service is currently running and must be stopped first!"
|
||||||
SET_CORE_STOP_CONFIRM="Do you want to stop the service?"
|
SET_CORE_STOP_CONFIRM="Do you want to stop the service?"
|
||||||
|
SET_UDP_BUFFER_ON="UDP buffer limit optimization is now enabled!"
|
||||||
|
SET_UDP_BUFFER_OFF="UDP buffer limit optimization is now disabled. Existing system values will not be lowered."
|
||||||
|
SET_UDP_BUFFER_RESTART="Restart the service to apply it to new connections."
|
||||||
|
|
||||||
# =================================================
|
# =================================================
|
||||||
# Backup / Restore / Reset
|
# Backup / Restore / Reset
|
||||||
|
|||||||
@@ -67,3 +67,21 @@ DNS_ADD_FAIL="Add failed"
|
|||||||
DNS_NOW="Current DNS: "
|
DNS_NOW="Current DNS: "
|
||||||
DNS_INPUT_NEW="Please input a new DNS address"
|
DNS_INPUT_NEW="Please input a new DNS address"
|
||||||
DNS_INPUT_RESET="or input r to reset the DNS address"
|
DNS_INPUT_RESET="or input r to reset the DNS address"
|
||||||
|
|
||||||
|
#===== Direct DNS Domains =====
|
||||||
|
DNS_DIRECT_MENU="Manage Direct DNS Domains"
|
||||||
|
DNS_DIRECT_DESC="Specify domains to use direct DNS resolution in mix/route mode"
|
||||||
|
DNS_DIRECT_TIP="Useful for LAN domains, intranet services, etc."
|
||||||
|
DNS_DIRECT_EXAMPLE="Examples:\n*.lan\n*.local\nnas.home"
|
||||||
|
DNS_DIRECT_EXIST="Added direct DNS domains:"
|
||||||
|
DNS_DIRECT_EMPTY="No custom direct DNS domains added"
|
||||||
|
DNS_DIRECT_EDIT="Enter number to delete, 'a' to add, 'r' to load preset, 't' to test"
|
||||||
|
DNS_DIRECT_ADD_LAN="Add LAN Domain"
|
||||||
|
DNS_DIRECT_LOAD_PRESET="Load Preset LAN Domains"
|
||||||
|
DNS_DIRECT_LOAD_OK="Preset LAN domains loaded successfully"
|
||||||
|
DNS_DIRECT_INPUT_HINT="Enter domain for direct DNS resolution (supports wildcards like *.lan)"
|
||||||
|
DNS_DIRECT_TEST="Test DNS Resolution"
|
||||||
|
DNS_DIRECT_TEST_INPUT="Enter domain to test"
|
||||||
|
DNS_DIRECT_TEST_RESULT="Resolution result:"
|
||||||
|
DNS_DIRECT_TEST_IN_LIST="✓ This domain is configured for direct DNS resolution"
|
||||||
|
DNS_DIRECT_TEST_NOT_IN_LIST="✗ This domain is not in the direct DNS list"
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
|
# s6 / Docker:自启状态以 configs 卷内标记为准,并同步到 s6 contents.d
|
||||||
|
|
||||||
|
enable_s6_autostart_marks() {
|
||||||
|
mkdir -p "$CRASHDIR/configs" /etc/s6-overlay/s6-rc.d/user/contents.d
|
||||||
|
touch "$CRASHDIR/configs/.autostart" /etc/s6-overlay/s6-rc.d/user/contents.d/afstart
|
||||||
|
}
|
||||||
|
|
||||||
|
disable_s6_autostart_marks() {
|
||||||
|
rm -f "$CRASHDIR/configs/.autostart" /etc/s6-overlay/s6-rc.d/user/contents.d/afstart
|
||||||
|
}
|
||||||
|
|
||||||
|
# 将旧版仅写在可写层的 s6 标记迁移到 configs
|
||||||
|
migrate_s6_autostart_mark() {
|
||||||
|
if [ -f /etc/s6-overlay/s6-rc.d/user/contents.d/afstart ] && [ ! -f "$CRASHDIR/configs/.autostart" ]; then
|
||||||
|
mkdir -p "$CRASHDIR/configs"
|
||||||
|
touch "$CRASHDIR/configs/.autostart"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
check_autostart(){
|
check_autostart(){
|
||||||
if [ "$start_old" = ON ];then
|
if [ "$start_old" = ON ];then
|
||||||
[ ! -f "$CRASHDIR"/.dis_startup ] && return 0
|
[ ! -f "$CRASHDIR"/.dis_startup ] && return 0
|
||||||
@@ -7,7 +26,8 @@ check_autostart(){
|
|||||||
elif ckcmd systemctl; then
|
elif ckcmd systemctl; then
|
||||||
[ "$(systemctl is-enabled shellcrash.service 2>&1)" = enabled ] && return 0
|
[ "$(systemctl is-enabled shellcrash.service 2>&1)" = enabled ] && return 0
|
||||||
elif grep -q 's6' /proc/1/comm; then
|
elif grep -q 's6' /proc/1/comm; then
|
||||||
[ -f /etc/s6-overlay/s6-rc.d/user/contents.d/afstart ] && return 0
|
migrate_s6_autostart_mark
|
||||||
|
[ -f "$CRASHDIR/configs/.autostart" ] && [ ! -f "$CRASHDIR"/.dis_startup ] && return 0
|
||||||
elif rc-status -r >/dev/null 2>&1; then
|
elif rc-status -r >/dev/null 2>&1; then
|
||||||
rc-update show default | grep -q "shellcrash" && return 0
|
rc-update show default | grep -q "shellcrash" && return 0
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
#$1=裸二进制字节数。仅当$TMPDIR在内存(tmpfs)时裸存才省RAM;
|
#$1=裸二进制字节数。仅当$TMPDIR在内存(tmpfs)时裸存才省RAM;
|
||||||
#再按$BINDIR文件系统估算裸二进制落盘体积(透明压缩fs约2:1),需留有余量($raw_margin,默认8M)
|
#再按$BINDIR文件系统估算裸二进制落盘体积(透明压缩fs约2:1),需留有余量($raw_margin,默认8M)
|
||||||
store_raw_worth_it(){
|
store_raw_worth_it(){
|
||||||
case "$(df -T "$TMPDIR" 2>/dev/null | awk 'END{print $2}')" in tmpfs|ramfs) ;; *) return 1 ;; esac
|
case "$(df -P -T "$TMPDIR" 2>/dev/null | awk 'END{print $2}')" in tmpfs|ramfs) ;; *) return 1 ;; esac
|
||||||
rom_free=$(df -k "$BINDIR" 2>/dev/null | awk 'END{print $4}') #KB
|
rom_free=$(df -P -k "$BINDIR" 2>/dev/null | awk 'END{print $4}') #KB
|
||||||
[ -z "$rom_free" ] && return 1
|
[ -z "$rom_free" ] && return 1
|
||||||
case "$(df -T "$BINDIR" 2>/dev/null | awk 'END{print $2}')" in
|
case "$(df -P -T "$BINDIR" 2>/dev/null | awk 'END{print $2}')" in
|
||||||
squashfs|ubifs|overlay|overlayfs) est=$(( ${1:-0}/1024/2 )) ;; #透明压缩,约2:1
|
squashfs|ubifs|overlay|overlayfs) est=$(( ${1:-0}/1024/2 )) ;; #透明压缩,约2:1
|
||||||
*) est=$(( ${1:-0}/1024 )) ;; #无压缩,全量
|
*) est=$(( ${1:-0}/1024 )) ;; #无压缩,全量
|
||||||
esac
|
esac
|
||||||
|
|||||||
@@ -16,6 +16,9 @@
|
|||||||
routing_mark=$((fwmark + 2))
|
routing_mark=$((fwmark + 2))
|
||||||
[ -z "$table" ] && table=100
|
[ -z "$table" ] && table=100
|
||||||
|
|
||||||
|
[ -z "$fakeip4" ] && fakeip4="198.18.0.0/15"
|
||||||
|
[ -z "$fakeip6" ] && fakeip6="2001:2::/64"
|
||||||
|
|
||||||
[ -z "$dns_nameserver" ] && {
|
[ -z "$dns_nameserver" ] && {
|
||||||
dns_nameserver='223.5.5.5, 1.2.4.8'
|
dns_nameserver='223.5.5.5, 1.2.4.8'
|
||||||
netstat -ntlup 2>/dev/null | grep -q '127.0.0.1:53' || ss -ntlup 2>/dev/null | grep -q '127.0.0.1:53' && dns_nameserver='127.0.0.1'
|
netstat -ntlup 2>/dev/null | grep -q '127.0.0.1:53' || ss -ntlup 2>/dev/null | grep -q '127.0.0.1:53' && dns_nameserver='127.0.0.1'
|
||||||
|
|||||||
+84
-30
@@ -1,41 +1,95 @@
|
|||||||
|
|
||||||
crondir="$(crond -h 2>&1 | grep -oE 'Default:.*' | awk -F ":" '{print $2}'| tr -d ' ')"
|
crondir="$(crond -h 2>&1 | grep -oE 'Default:.*' | awk -F ":" '{print $2}'| tr -d ' ')"
|
||||||
[ ! -w "$crondir" ] && crondir="/etc/storage/cron/crontabs"
|
[ ! -w "$crondir" ] && crondir="/etc/storage/cron/crontabs"
|
||||||
[ ! -w "$crondir" ] && crondir="/var/spool/cron/crontabs"
|
[ ! -w "$crondir" ] && crondir="/var/spool/cron/crontabs"
|
||||||
[ ! -w "$crondir" ] && crondir="/var/spool/cron"
|
[ ! -w "$crondir" ] && crondir="/var/spool/cron"
|
||||||
[ -z "$USER" ] && USER=$(whoami 2>/dev/null)
|
[ -z "$USER" ] && USER=$(id -un)
|
||||||
[ -z "$TASKCFGDIR" ] && TASKCFGDIR="$CRASHDIR"/configs/task
|
[ -z "$TASKCFGDIR" ] && TASKCFGDIR="$CRASHDIR"/configs/task
|
||||||
tmpcron=/tmp/cron_tmp
|
|
||||||
touch "$tmpcron"
|
|
||||||
|
|
||||||
cronadd() { #定时任务工具
|
# ShellCrash 使用的 ash/bash(以及 dash)均支持 test -O。
|
||||||
if crontab -h 2>&1 | grep -q '\-l'; then
|
# shellcheck disable=SC3067
|
||||||
crontab "$1"
|
croncheck() { #在任何写操作前检查实例管理权限,保留普通用户自己的安装
|
||||||
elif [ -w "$crondir" ];then
|
cron_uid=$(id -u) || return 1
|
||||||
cat "$1" >"$crondir"/"$USER" && cru a REFRESH "0 0 1 1 * /bin/true" 2>/dev/null
|
[ "$cron_uid" = 0 ] && return 0
|
||||||
else
|
if [ ! -O "$CRASHDIR/configs/ShellCrash.cfg" ] || [ ! -w "$CRASHDIR/configs/ShellCrash.cfg" ]; then
|
||||||
echo "找不到可用的crond或者crontab应用!No available crond or crontab application can be found!"
|
echo '无权管理此 ShellCrash 实例,请使用安装用户或 root。' >&2
|
||||||
fi
|
|
||||||
}
|
|
||||||
cronload() { #定时任务工具
|
|
||||||
if crontab -h 2>&1 | grep -q '\-l'; then
|
|
||||||
crontab -l
|
|
||||||
elif [ -f "$crondir/$USER" ];then
|
|
||||||
cat "$crondir"/"$USER" 2>/dev/null
|
|
||||||
else
|
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
for cron_pid in $(pidof CrashCore 2>/dev/null); do
|
||||||
|
if [ ! -O "/proc/$cron_pid" ]; then
|
||||||
|
echo '无权管理其他用户启动的 CrashCore。' >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
}
|
}
|
||||||
cronset() { #定时任务设置
|
|
||||||
# 参数1代表要移除的关键字,参数2代表要添加的任务语句
|
cronadd() ( #定时任务工具;子 shell 隔离临时变量和清理 trap
|
||||||
cronload | grep -v '^$' | grep -vF "$1" >"$tmpcron"
|
croncheck || exit 1
|
||||||
[ -n "$2" ] && echo "$2" >>"$tmpcron"
|
[ -f "$1" ] && [ -r "$1" ] || exit 1
|
||||||
cronadd "$tmpcron"
|
if crontab -h 2>&1 | grep -q '\-l'; then
|
||||||
#华硕/Padavan固件存档在本地,其他则删除
|
crontab "$1"
|
||||||
if [ -d /jffs ] || [ -d /etc/storage/ShellCrash ];then
|
elif [ -w "$crondir" ]; then
|
||||||
mkdir -p "$TASKCFGDIR"
|
cron_user=$(id -un) || exit 1
|
||||||
mv -f "$tmpcron" "$TASKCFGDIR"/cron
|
cron_stage=$(mktemp "$crondir/.shellcrash.XXXXXX") || exit 1
|
||||||
|
trap 'rm -f "$cron_stage"' 0
|
||||||
|
trap 'exit 1' 1 2 3 15
|
||||||
|
[ ! -e "$crondir/$cron_user" ] || cp -p "$crondir/$cron_user" "$cron_stage" || exit 1
|
||||||
|
cat "$1" >"$cron_stage" && mv -f "$cron_stage" "$crondir/$cron_user" || exit 1
|
||||||
|
if command -v cru >/dev/null 2>&1; then
|
||||||
|
cru a REFRESH "0 0 1 1 * /bin/true"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
rm -f "$tmpcron"
|
echo '找不到可用的 crond 或 crontab!No available crond or crontab!' >&2
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
}
|
)
|
||||||
|
|
||||||
|
cronload() (
|
||||||
|
cron_user=$(id -un) || exit 1
|
||||||
|
if crontab -h 2>&1 | grep -q '\-l'; then
|
||||||
|
cron_text=$(LC_ALL=C crontab -l 2>&1)
|
||||||
|
cron_status=$?
|
||||||
|
if [ "$cron_status" = 0 ]; then
|
||||||
|
[ -z "$cron_text" ] || printf '%s\n' "$cron_text"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
#首次使用没有 crontab 是合法空表,其他错误必须传回调用者。
|
||||||
|
case "$cron_text" in
|
||||||
|
"no crontab for $cron_user" | "crontab: can't open '$cron_user': No such file or directory") exit 0 ;;
|
||||||
|
esac
|
||||||
|
printf '%s\n' "$cron_text" >&2
|
||||||
|
exit "$cron_status"
|
||||||
|
elif [ -d "$crondir" ] && [ -r "$crondir" ] && [ -x "$crondir" ]; then
|
||||||
|
[ -e "$crondir/$cron_user" ] || [ -L "$crondir/$cron_user" ] || exit 0
|
||||||
|
cat "$crondir/$cron_user"
|
||||||
|
else
|
||||||
|
echo '无法读取原有 crontab,已取消修改。' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
)
|
||||||
|
|
||||||
|
cronupdate() ( #成功读取、生成后才提交;参数是读取 stdin 的过滤命令
|
||||||
|
croncheck || exit 1
|
||||||
|
cron_tmp=$(mktemp -d /tmp/ShellCrash-cron.XXXXXX) || exit 1
|
||||||
|
cron_saved=
|
||||||
|
trap 'rm -rf "$cron_tmp"; [ -z "$cron_saved" ] || rm -f "$cron_saved"' 0
|
||||||
|
trap 'exit 1' 1 2 3 15
|
||||||
|
cronload >"$cron_tmp/old" || exit 1
|
||||||
|
"$@" <"$cron_tmp/old" >"$cron_tmp/new" || exit 1
|
||||||
|
#先准备华硕/Padavan 的持久化副本;任何提交前的写入失败都保留原表。
|
||||||
|
if [ "$cron_persist" = true ] && { [ -d /jffs ] || [ -d /etc/storage/ShellCrash ]; }; then
|
||||||
|
mkdir -p "$TASKCFGDIR" || exit 1
|
||||||
|
cron_saved=$(mktemp "$TASKCFGDIR/.cron.XXXXXX") || exit 1
|
||||||
|
cat "$cron_tmp/new" >"$cron_saved" || exit 1
|
||||||
|
fi
|
||||||
|
cronadd "$cron_tmp/new" || exit 1
|
||||||
|
[ -z "$cron_saved" ] || mv -f "$cron_saved" "$TASKCFGDIR/cron"
|
||||||
|
)
|
||||||
|
|
||||||
|
cronset() ( #参数1:移除的文字;参数2:新增任务。空结果也是合法 crontab。
|
||||||
|
cron_persist=true
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
CRON_KEY="$1" CRON_TASK="$2" cronupdate awk '
|
||||||
|
NF && !index($0, ENVIRON["CRON_KEY"]) { print }
|
||||||
|
END { if (ENVIRON["CRON_TASK"] != "") print ENVIRON["CRON_TASK"] }
|
||||||
|
'
|
||||||
|
)
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ settings() {
|
|||||||
echo "$crashcore" | grep -q 'singbox' && sniffer=ON
|
echo "$crashcore" | grep -q 'singbox' && sniffer=ON
|
||||||
}
|
}
|
||||||
[ -z "$dns_mod" ] && dns_mod='redir_host'
|
[ -z "$dns_mod" ] && dns_mod='redir_host'
|
||||||
|
[ -z "$udp_buffer" ] && udp_buffer=OFF
|
||||||
|
|
||||||
comp_box "\033[30;47m$SET_MENU_TITLE\033[0m"
|
comp_box "\033[30;47m$SET_MENU_TITLE\033[0m"
|
||||||
content_line "1) $SET_MENU_REDIR\t\033[36m$redir_mod$MENU_MOD\033[0m"
|
content_line "1) $SET_MENU_REDIR\t\033[36m$redir_mod$MENU_MOD\033[0m"
|
||||||
@@ -27,6 +28,7 @@ settings() {
|
|||||||
content_line "6) $SET_MENU_ADV_PORT"
|
content_line "6) $SET_MENU_ADV_PORT"
|
||||||
}
|
}
|
||||||
content_line "7) $SET_MENU_IPV6\t\033[36m$ipv6_redir\033[0m"
|
content_line "7) $SET_MENU_IPV6\t\033[36m$ipv6_redir\033[0m"
|
||||||
|
content_line "8) $SET_MENU_UDP_BUFFER\t\033[36m$udp_buffer\033[0m"
|
||||||
btm_box "" \
|
btm_box "" \
|
||||||
"a) \033[31m$SET_MENU_RESET\033[0m" \
|
"a) \033[31m$SET_MENU_RESET\033[0m" \
|
||||||
"b) \033[36m$SET_MENU_LANG\033[0m" \
|
"b) \033[36m$SET_MENU_LANG\033[0m" \
|
||||||
@@ -143,6 +145,18 @@ settings() {
|
|||||||
7)
|
7)
|
||||||
set_ipv6
|
set_ipv6
|
||||||
;;
|
;;
|
||||||
|
8)
|
||||||
|
if [ "$udp_buffer" = "ON" ]; then
|
||||||
|
udp_buffer=OFF
|
||||||
|
msg_alert "\033[33m$SET_UDP_BUFFER_OFF\033[0m" \
|
||||||
|
"$SET_UDP_BUFFER_RESTART"
|
||||||
|
else
|
||||||
|
udp_buffer=ON
|
||||||
|
msg_alert "\033[32m$SET_UDP_BUFFER_ON\033[0m" \
|
||||||
|
"$SET_UDP_BUFFER_RESTART"
|
||||||
|
fi
|
||||||
|
setconfig udp_buffer "$udp_buffer"
|
||||||
|
;;
|
||||||
a)
|
a)
|
||||||
BACK_TAR="$CRASHDIR/configs.tar.gz"
|
BACK_TAR="$CRASHDIR/configs.tar.gz"
|
||||||
comp_box "1) $SET_BACKUP" \
|
comp_box "1) $SET_BACKUP" \
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ allow_autostart() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
ckcmd systemctl && systemctl enable shellcrash.service >/dev/null 2>&1
|
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
|
grep -q 's6' /proc/1/comm && enable_s6_autostart_marks
|
||||||
rc-status -r >/dev/null 2>&1 && rc-update add shellcrash default >/dev/null 2>&1
|
rc-status -r >/dev/null 2>&1 && rc-update add shellcrash default >/dev/null 2>&1
|
||||||
rm -rf "$CRASHDIR"/.dis_startup
|
rm -rf "$CRASHDIR"/.dis_startup
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,7 @@ allow_autostart() {
|
|||||||
disable_autostart() {
|
disable_autostart() {
|
||||||
[ -d /etc/rc.d ] && cd /etc/rc.d && rm -rf *shellcrash >/dev/null 2>&1 && cd - >/dev/null
|
[ -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
|
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
|
grep -q 's6' /proc/1/comm && disable_s6_autostart_marks
|
||||||
rc-status -r >/dev/null 2>&1 && rc-update del shellcrash default >/dev/null 2>&1
|
rc-status -r >/dev/null 2>&1 && rc-update del shellcrash default >/dev/null 2>&1
|
||||||
touch "$CRASHDIR"/.dis_startup
|
touch "$CRASHDIR"/.dis_startup
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-10
@@ -23,7 +23,7 @@ set_cron() {
|
|||||||
"0) $TASK5_NO"
|
"0) $TASK5_NO"
|
||||||
read -r -p "$COMMON_INPUT> " res
|
read -r -p "$COMMON_INPUT> " res
|
||||||
if [ "$res" = '1' ]; then
|
if [ "$res" = '1' ]; then
|
||||||
task_txt="$min $hour * * $week $CRASHDIR/task/task.sh $task_id $cron_time$task_name"
|
task_txt="$min $hour * * $week $CRASHDIR/task/task.sh $task_id \"$cron_time$task_name\""
|
||||||
cronset "$cron_time$task_name" "$task_txt"
|
cronset "$cron_time$task_name" "$task_txt"
|
||||||
msg_alert -t 0 "$TASK5_TASK_PREFIX$cron_time$task_name$TASK5_TASK_ADDED"
|
msg_alert -t 0 "$TASK5_TASK_PREFIX$cron_time$task_name$TASK5_TASK_ADDED"
|
||||||
fi
|
fi
|
||||||
@@ -38,11 +38,11 @@ set_service() {
|
|||||||
[ -s "$task_file" ] && sed -i "/$3/d" "$task_file"
|
[ -s "$task_file" ] && sed -i "/$3/d" "$task_file"
|
||||||
# 运行时每分钟执行的任务特殊处理
|
# 运行时每分钟执行的任务特殊处理
|
||||||
if [ "$1" = "running" ]; then
|
if [ "$1" = "running" ]; then
|
||||||
task_txt="$4 $CRASHDIR/task/task.sh $2 $3"
|
task_txt="$4 $CRASHDIR/task/task.sh $2 \"$3\""
|
||||||
echo "$task_txt" >>"$task_file"
|
echo "$task_txt" >>"$task_file"
|
||||||
[ -n "$(pidof CrashCore)" ] && cronset "$3" "$task_txt"
|
[ -n "$(pidof CrashCore)" ] && cronset "$3" "$task_txt"
|
||||||
else
|
else
|
||||||
echo "$CRASHDIR/task/task.sh $2 $3" >>"$task_file"
|
echo "$CRASHDIR/task/task.sh $2 \"$3\"" >>"$task_file"
|
||||||
fi
|
fi
|
||||||
content_line "【$3】\033[32m$COMMON_SUCCESS\033[0m"
|
content_line "【$3】\033[32m$COMMON_SUCCESS\033[0m"
|
||||||
sleep 1
|
sleep 1
|
||||||
@@ -144,11 +144,12 @@ task_del() {
|
|||||||
# 删除定时任务
|
# 删除定时任务
|
||||||
cronset "$1"
|
cronset "$1"
|
||||||
# 删除条件任务
|
# 删除条件任务
|
||||||
sed -i "/$1/d" "$TASKCFGDIR"/cron 2>/dev/null
|
[ -f "$TASKCFGDIR"/cron ] && sed -i "/$1/d" "$TASKCFGDIR"/cron 2>/dev/null
|
||||||
sed -i "/$1/d" "$TASKCFGDIR"/bfstart 2>/dev/null
|
[ -f "$TASKCFGDIR"/bfstart ] && sed -i "/$1/d" "$TASKCFGDIR"/bfstart 2>/dev/null
|
||||||
sed -i "/$1/d" "$TASKCFGDIR"/afstart 2>/dev/null
|
[ -f "$TASKCFGDIR"/afstart ] && sed -i "/$1/d" "$TASKCFGDIR"/afstart 2>/dev/null
|
||||||
sed -i "/$1/d" "$TASKCFGDIR"/running 2>/dev/null
|
[ -f "$TASKCFGDIR"/running ] && sed -i "/$1/d" "$TASKCFGDIR"/running 2>/dev/null
|
||||||
sed -i "/$1/d" "$TASKCFGDIR"/affirewall 2>/dev/null
|
[ -f "$TASKCFGDIR"/affirewall ] && sed -i "/$1/d" "$TASKCFGDIR"/affirewall 2>/dev/null
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# 任务条件选择菜单
|
# 任务条件选择菜单
|
||||||
@@ -293,7 +294,10 @@ task_manager() {
|
|||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
task_des=$(echo "$task_txt" | awk '{print $2}')
|
task_des=${task_txt#* }
|
||||||
|
task_des=${task_des#"${task_des%%[! ]*}"}
|
||||||
|
task_des=${task_des#\"}
|
||||||
|
task_des=${task_des%\"}
|
||||||
task_name=$(cat "$CRASHDIR"/task/task_${i18n}.list "$TASKCFGDIR"/task.user 2>/dev/null | grep "$task_id" | awk -F '#' '{print $3}')
|
task_name=$(cat "$CRASHDIR"/task/task_${i18n}.list "$TASKCFGDIR"/task.user 2>/dev/null | grep "$task_id" | awk -F '#' '{print $3}')
|
||||||
comp_box "$TASK5_CURRENT_TASK\033[36m$task_des\033[0m"
|
comp_box "$TASK5_CURRENT_TASK\033[36m$task_des\033[0m"
|
||||||
btm_box "1) $TASK5_EDIT_TASK" \
|
btm_box "1) $TASK5_EDIT_TASK" \
|
||||||
@@ -359,7 +363,7 @@ task_recom() {
|
|||||||
separator_line "="
|
separator_line "="
|
||||||
set_service running "106" "$TASK_RECOM_ITEM_1" "*/10 * * * *"
|
set_service running "106" "$TASK_RECOM_ITEM_1" "*/10 * * * *"
|
||||||
set_service afstart "107" "$TASK_RECOM_ITEM_2"
|
set_service afstart "107" "$TASK_RECOM_ITEM_2"
|
||||||
cronset "$TASK_RECOM_ITEM_3" "0 3 * * * ${CRASHDIR}/task/task.sh 103 $TASK_RECOM_ITEM_3" &&
|
cronset "$TASK_RECOM_ITEM_3" "0 3 * * * ${CRASHDIR}/task/task.sh 103 \"$TASK_RECOM_ITEM_3\"" &&
|
||||||
content_line "【$TASK_RECOM_ITEM_3】\033[32m$COMMON_SUCCESS\033[0m"
|
content_line "【$TASK_RECOM_ITEM_3】\033[32m$COMMON_SUCCESS\033[0m"
|
||||||
separator_line "="
|
separator_line "="
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ set_dns_mod() {
|
|||||||
[ "$dns_mod" = "mix" ] &&
|
[ "$dns_mod" = "mix" ] &&
|
||||||
content_line "8) \033[33m$DNS_FAKEIP_MENU\033[0m"
|
content_line "8) \033[33m$DNS_FAKEIP_MENU\033[0m"
|
||||||
content_line "9) \033[36m$DNS_ADV_MENU\033[0m"
|
content_line "9) \033[36m$DNS_ADV_MENU\033[0m"
|
||||||
|
[ "$dns_mod" = "mix" ] || [ "$dns_mod" = "route" ] &&
|
||||||
|
content_line "a) \033[32m$DNS_DIRECT_MENU\033[0m"
|
||||||
content_line ""
|
content_line ""
|
||||||
content_line "0) $COMMON_BACK"
|
content_line "0) $COMMON_BACK"
|
||||||
separator_line "="
|
separator_line "="
|
||||||
@@ -116,6 +118,13 @@ set_dns_mod() {
|
|||||||
9)
|
9)
|
||||||
set_dns_adv
|
set_dns_adv
|
||||||
;;
|
;;
|
||||||
|
a)
|
||||||
|
if [ "$dns_mod" = "mix" ] || [ "$dns_mod" = "route" ]; then
|
||||||
|
dns_direct_domains
|
||||||
|
else
|
||||||
|
msg_alert "\033[33m直连域名功能仅在 mix/route 模式下可用!\033[0m"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
errornum
|
errornum
|
||||||
;;
|
;;
|
||||||
@@ -172,6 +181,96 @@ fake_ip_filter() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 直连域名管理
|
||||||
|
dns_direct_domains() {
|
||||||
|
while true; do
|
||||||
|
comp_box "\033[32m$DNS_DIRECT_DESC\033[0m" \
|
||||||
|
"\033[36m$DNS_DIRECT_TIP\033[0m" \
|
||||||
|
"$DNS_DIRECT_EXAMPLE"
|
||||||
|
if [ -s "$CRASHDIR/configs/dns_direct_domains" ]; then
|
||||||
|
content_line "\033[33m$DNS_DIRECT_EXIST\033[0m"
|
||||||
|
content_line ""
|
||||||
|
awk '{print NR") "$1}' "$CRASHDIR/configs/dns_direct_domains" |
|
||||||
|
while IFS= read -r line; do
|
||||||
|
content_line "$line"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
content_line "\033[33m$DNS_DIRECT_EMPTY\033[0m"
|
||||||
|
fi
|
||||||
|
btm_box "" \
|
||||||
|
"a) $DNS_DIRECT_ADD_LAN" \
|
||||||
|
"r) $DNS_DIRECT_LOAD_PRESET" \
|
||||||
|
"t) $DNS_DIRECT_TEST" \
|
||||||
|
"0) $COMMON_BACK"
|
||||||
|
read -r -p "$DNS_DIRECT_EDIT> " input
|
||||||
|
case "$input" in
|
||||||
|
"" | 0)
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
a)
|
||||||
|
comp_box "$DNS_DIRECT_INPUT_HINT"
|
||||||
|
btm_box "1) $DNS_CONFIRM_OK" \
|
||||||
|
"0) $COMMON_BACK"
|
||||||
|
read -r -p "$DNS_INPUT> " domain
|
||||||
|
case "$domain" in
|
||||||
|
0)
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if echo "$domain" >>"$CRASHDIR/configs/dns_direct_domains"; then
|
||||||
|
msg_alert "\033[32m$DNS_ADD_OK\033[0m"
|
||||||
|
else
|
||||||
|
msg_alert "\033[31m$DNS_ADD_FAIL\033[0m"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
r)
|
||||||
|
if [ -s "$CRASHDIR/public/dns_direct_domains.list" ]; then
|
||||||
|
cat "$CRASHDIR/public/dns_direct_domains.list" >>"$CRASHDIR/configs/dns_direct_domains"
|
||||||
|
msg_alert "\033[32m$DNS_DIRECT_LOAD_OK\033[0m"
|
||||||
|
else
|
||||||
|
msg_alert "\033[31m预设文件不存在!\033[0m"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
t)
|
||||||
|
comp_box "$DNS_DIRECT_TEST_INPUT"
|
||||||
|
btm_box "1) $DNS_CONFIRM_OK" \
|
||||||
|
"0) $COMMON_BACK"
|
||||||
|
read -r -p "$DNS_INPUT> " test_domain
|
||||||
|
case "$test_domain" in
|
||||||
|
0)
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# 使用本地 DNS 解析
|
||||||
|
result=$(nslookup "$test_domain" 127.0.0.1:$dns_port 2>&1 || echo "解析失败")
|
||||||
|
comp_box "$DNS_DIRECT_TEST_RESULT" \
|
||||||
|
"$result"
|
||||||
|
# 判断是否在直连列表中
|
||||||
|
if [ -f "$CRASHDIR/configs/dns_direct_domains" ] && grep -qF "$test_domain" "$CRASHDIR/configs/dns_direct_domains"; then
|
||||||
|
content_line "\033[32m$DNS_DIRECT_TEST_IN_LIST\033[0m"
|
||||||
|
else
|
||||||
|
content_line "\033[33m$DNS_DIRECT_TEST_NOT_IN_LIST\033[0m"
|
||||||
|
fi
|
||||||
|
btm_box "0) $COMMON_BACK"
|
||||||
|
read -r -p "$COMMON_INPUT> " res
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if [ "$input" -ge 1 ] 2>/dev/null; then
|
||||||
|
if sed -i "${input}d" "$CRASHDIR/configs/dns_direct_domains"; then
|
||||||
|
msg_alert "\033[32m$DNS_REMOVE_OK\033[0m"
|
||||||
|
else
|
||||||
|
msg_alert "\033[31m$DNS_REMOVE_FAIL\033[0m"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
# DNS详细设置
|
# DNS详细设置
|
||||||
set_dns_adv() {
|
set_dns_adv() {
|
||||||
while true; do
|
while true; do
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ forwhat() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
ckcmd systemctl && [ "$(cat /proc/1/comm)" = "systemd" ] && systemctl enable shellcrash.service >/dev/null 2>&1
|
ckcmd systemctl && [ "$(cat /proc/1/comm)" = "systemd" ] && systemctl enable shellcrash.service >/dev/null 2>&1
|
||||||
|
grep -q 's6' /proc/1/comm && enable_s6_autostart_marks
|
||||||
rm -rf "$CRASHDIR"/.dis_startup
|
rm -rf "$CRASHDIR"/.dis_startup
|
||||||
autostart=enable
|
autostart=enable
|
||||||
# 检测IP转发
|
# 检测IP转发
|
||||||
|
|||||||
+12
-9
@@ -6,11 +6,13 @@
|
|||||||
cd $(dirname $0)
|
cd $(dirname $0)
|
||||||
pwd
|
pwd
|
||||||
)
|
)
|
||||||
|
. "$CRASHDIR"/libs/set_cron.sh
|
||||||
|
croncheck || exit 1
|
||||||
. "$CRASHDIR"/libs/get_config.sh
|
. "$CRASHDIR"/libs/get_config.sh
|
||||||
#加载工具
|
#加载工具
|
||||||
. "$CRASHDIR"/libs/set_config.sh
|
. "$CRASHDIR"/libs/set_config.sh
|
||||||
. "$CRASHDIR"/libs/set_cron.sh
|
|
||||||
. "$CRASHDIR"/libs/check_cmd.sh
|
. "$CRASHDIR"/libs/check_cmd.sh
|
||||||
|
. "$CRASHDIR"/libs/check_autostart.sh
|
||||||
. "$CRASHDIR"/libs/compare.sh
|
. "$CRASHDIR"/libs/compare.sh
|
||||||
. "$CRASHDIR"/libs/logger.sh
|
. "$CRASHDIR"/libs/logger.sh
|
||||||
. "$CRASHDIR"/libs/web_save.sh
|
. "$CRASHDIR"/libs/web_save.sh
|
||||||
@@ -35,7 +37,9 @@ start_l(){
|
|||||||
case "$1" in
|
case "$1" in
|
||||||
|
|
||||||
start)
|
start)
|
||||||
[ -n "$(pidof CrashCore)" ] && $0 stop #禁止多实例
|
if [ -n "$(pidof CrashCore)" ]; then #禁止多实例
|
||||||
|
"$0" stop || exit 1
|
||||||
|
fi
|
||||||
stop_firewall #清理路由策略
|
stop_firewall #清理路由策略
|
||||||
rm -f "$CRASHDIR"/\.start_error #移除自启失败标记
|
rm -f "$CRASHDIR"/\.start_error #移除自启失败标记
|
||||||
#使用不同方式启动服务
|
#使用不同方式启动服务
|
||||||
@@ -54,7 +58,7 @@ start)
|
|||||||
systemctl start shellcrash.service || . "$CRASHDIR"/starts/start_error.sh
|
systemctl start shellcrash.service || . "$CRASHDIR"/starts/start_error.sh
|
||||||
elif grep -q 's6' /proc/1/comm; then
|
elif grep -q 's6' /proc/1/comm; then
|
||||||
bfstart && /command/s6-svc -u /run/service/shellcrash && {
|
bfstart && /command/s6-svc -u /run/service/shellcrash && {
|
||||||
[ ! -f "$CRASHDIR"/.dis_startup ] && touch /etc/s6-overlay/s6-rc.d/user/contents.d/afstart
|
[ ! -f "$CRASHDIR"/.dis_startup ] && enable_s6_autostart_marks
|
||||||
afstart &
|
afstart &
|
||||||
}
|
}
|
||||||
elif rc-status -r >/dev/null 2>&1; then
|
elif rc-status -r >/dev/null 2>&1; then
|
||||||
@@ -68,9 +72,7 @@ stop)
|
|||||||
logger ShellCrash服务即将关闭......
|
logger ShellCrash服务即将关闭......
|
||||||
[ -n "$(pidof CrashCore)" ] && web_save #保存面板配置
|
[ -n "$(pidof CrashCore)" ] && web_save #保存面板配置
|
||||||
#清理定时任务
|
#清理定时任务
|
||||||
cronload | grep -vE '^$|start_legacy_wd.sh|运行时每' > "$TMPDIR"/cron_tmp
|
cronupdate awk 'NF && !/start_legacy_wd.sh|运行时每/' || exit 1
|
||||||
cronadd "$TMPDIR"/cron_tmp
|
|
||||||
rm -f "$TMPDIR"/cron_tmp
|
|
||||||
#停止tg_bot
|
#停止tg_bot
|
||||||
. "$CRASHDIR"/menus/bot_tg_service.sh && bot_tg_stop
|
. "$CRASHDIR"/menus/bot_tg_service.sh && bot_tg_stop
|
||||||
#多种方式结束进程
|
#多种方式结束进程
|
||||||
@@ -95,8 +97,7 @@ stop)
|
|||||||
rm -rf "$TMPDIR"/CrashCore
|
rm -rf "$TMPDIR"/CrashCore
|
||||||
;;
|
;;
|
||||||
restart)
|
restart)
|
||||||
$0 stop
|
"$0" stop && "$0" start
|
||||||
$0 start
|
|
||||||
;;
|
;;
|
||||||
init)
|
init)
|
||||||
. "$CRASHDIR"/starts/general_init.sh
|
. "$CRASHDIR"/starts/general_init.sh
|
||||||
@@ -109,7 +110,9 @@ daemon)
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
debug)
|
debug)
|
||||||
[ -n "$(pidof CrashCore)" ] && $0 stop >/dev/null #禁止多实例
|
if [ -n "$(pidof CrashCore)" ]; then #禁止多实例
|
||||||
|
"$0" stop >/dev/null || exit 1
|
||||||
|
fi
|
||||||
stop_firewall >/dev/null #清理路由策略
|
stop_firewall >/dev/null #清理路由策略
|
||||||
bfstart
|
bfstart
|
||||||
if [ -n "$2" ]; then
|
if [ -n "$2" ]; then
|
||||||
|
|||||||
@@ -7,11 +7,12 @@
|
|||||||
cd ..
|
cd ..
|
||||||
pwd
|
pwd
|
||||||
)
|
)
|
||||||
|
. "$CRASHDIR"/libs/set_cron.sh
|
||||||
|
croncheck || exit 1
|
||||||
. "$CRASHDIR"/libs/get_config.sh
|
. "$CRASHDIR"/libs/get_config.sh
|
||||||
#加载工具
|
#加载工具
|
||||||
. "$CRASHDIR"/libs/check_cmd.sh
|
. "$CRASHDIR"/libs/check_cmd.sh
|
||||||
. "$CRASHDIR"/libs/logger.sh
|
. "$CRASHDIR"/libs/logger.sh
|
||||||
. "$CRASHDIR"/libs/set_cron.sh
|
|
||||||
#缺省值
|
#缺省值
|
||||||
[ -z "$firewall_area" ] && firewall_area=1
|
[ -z "$firewall_area" ] && firewall_area=1
|
||||||
#延迟启动
|
#延迟启动
|
||||||
@@ -37,14 +38,24 @@ if [ -n "$test" -o -n "$(pidof CrashCore)" ]; then
|
|||||||
} &
|
} &
|
||||||
ckcmd mtd_storage.sh && mtd_storage.sh save >/dev/null 2>&1 #Padavan保存/etc/storage
|
ckcmd mtd_storage.sh && mtd_storage.sh save >/dev/null 2>&1 #Padavan保存/etc/storage
|
||||||
#加载定时任务
|
#加载定时任务
|
||||||
cronload | grep -v '^$' >"$TMPDIR"/cron_tmp
|
set -- -
|
||||||
[ -s "$TASKCFGDIR"/cron ] && cat "$TASKCFGDIR"/cron >>"$TMPDIR"/cron_tmp
|
for cron_file in "$TASKCFGDIR/cron" "$TASKCFGDIR/running"; do
|
||||||
[ -s "$TASKCFGDIR"/running ] && cat "$TASKCFGDIR"/running >>"$TMPDIR"/cron_tmp
|
[ ! -e "$cron_file" ] || set -- "$@" "$cron_file"
|
||||||
[ "$bot_tg_service" = ON ] && echo "* * * * * /bin/sh $CRASHDIR/starts/start_legacy_wd.sh bot_tg #ShellCrash-TG_BOT守护进程" >>"$TMPDIR"/cron_tmp
|
done
|
||||||
[ "$start_old" = ON ] && echo "* * * * * /bin/sh $CRASHDIR/starts/start_legacy_wd.sh shellcrash #ShellCrash保守模式守护进程" >>"$TMPDIR"/cron_tmp
|
# shellcheck disable=SC2016
|
||||||
awk '!x[$0]++' "$TMPDIR"/cron_tmp >"$TMPDIR"/cron_tmp2 #删除重复行
|
CRON_BOT="$bot_tg_service" CRON_LEGACY="$start_old" CRON_DIR="$CRASHDIR" cronupdate awk '
|
||||||
cronadd "$TMPDIR"/cron_tmp2
|
NF && !seen[$0]++ { print }
|
||||||
rm -f "$TMPDIR"/cron_tmp "$TMPDIR"/cron_tmp2
|
END {
|
||||||
|
if (ENVIRON["CRON_BOT"] == "ON") {
|
||||||
|
line = "* * * * * /bin/sh " ENVIRON["CRON_DIR"] "/starts/start_legacy_wd.sh bot_tg #ShellCrash-TG_BOT守护进程"
|
||||||
|
if (!seen[line]++) print line
|
||||||
|
}
|
||||||
|
if (ENVIRON["CRON_LEGACY"] == "ON") {
|
||||||
|
line = "* * * * * /bin/sh " ENVIRON["CRON_DIR"] "/starts/start_legacy_wd.sh shellcrash #ShellCrash保守模式守护进程"
|
||||||
|
if (!seen[line]++) print line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' "$@" || exit 1
|
||||||
#加载条件任务
|
#加载条件任务
|
||||||
[ -s "$TASKCFGDIR"/afstart ] && { . "$TASKCFGDIR"/afstart; } &
|
[ -s "$TASKCFGDIR"/afstart ] && { . "$TASKCFGDIR"/afstart; } &
|
||||||
[ -s "$TASKCFGDIR"/affirewall -a -s /etc/init.d/firewall -a ! -f /etc/init.d/firewall.bak ] && {
|
[ -s "$TASKCFGDIR"/affirewall -a -s /etc/init.d/firewall -a ! -f /etc/init.d/firewall.bak ] && {
|
||||||
|
|||||||
@@ -23,6 +23,24 @@
|
|||||||
[ -z "$redir_mod" ] && firewall_area='4'
|
[ -z "$redir_mod" ] && firewall_area='4'
|
||||||
routing_mark=$((fwmark + 2))
|
routing_mark=$((fwmark + 2))
|
||||||
|
|
||||||
|
set_udp_buffer_limit() {
|
||||||
|
[ "$udp_buffer" = "ON" ] || return 0
|
||||||
|
|
||||||
|
udp_buffer_limit=16777216
|
||||||
|
#同时提高上限与默认值:部分Mihomo/quic-go构建不显式setsockopt,仅继承default
|
||||||
|
for udp_buffer_file in /proc/sys/net/core/rmem_max /proc/sys/net/core/wmem_max \
|
||||||
|
/proc/sys/net/core/rmem_default /proc/sys/net/core/wmem_default; do
|
||||||
|
[ -w "$udp_buffer_file" ] || continue
|
||||||
|
udp_buffer_current=$(cat "$udp_buffer_file" 2>/dev/null)
|
||||||
|
case "$udp_buffer_current" in
|
||||||
|
'' | *[!0-9]*) continue ;;
|
||||||
|
esac
|
||||||
|
[ "$udp_buffer_current" -lt "$udp_buffer_limit" ] &&
|
||||||
|
printf '%s\n' "$udp_buffer_limit" >"$udp_buffer_file"
|
||||||
|
done
|
||||||
|
unset udp_buffer_limit udp_buffer_file udp_buffer_current
|
||||||
|
}
|
||||||
|
|
||||||
makehtml() { #生成面板跳转文件
|
makehtml() { #生成面板跳转文件
|
||||||
cat >"$BINDIR"/ui/index.html <<EOF
|
cat >"$BINDIR"/ui/index.html <<EOF
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
@@ -78,6 +96,8 @@ EOF
|
|||||||
[ "$network_check" != "OFF" ] && [ ! -f "$TMPDIR"/crash_start_time ] && ckcmd ping && . "$CRASHDIR"/starts/check_network.sh && check_network
|
[ "$network_check" != "OFF" ] && [ ! -f "$TMPDIR"/crash_start_time ] && ckcmd ping && . "$CRASHDIR"/starts/check_network.sh && check_network
|
||||||
[ ! -d "$BINDIR"/ui ] && mkdir -p "$BINDIR"/ui
|
[ ! -d "$BINDIR"/ui ] && mkdir -p "$BINDIR"/ui
|
||||||
[ -z "$crashcore" ] && crashcore=meta
|
[ -z "$crashcore" ] && crashcore=meta
|
||||||
|
#按需提高UDP套接字缓冲上限,改善Hysteria2等QUIC协议的吞吐
|
||||||
|
set_udp_buffer_limit
|
||||||
#执行条件任务
|
#执行条件任务
|
||||||
[ -s "$TASKCFGDIR"/bfstart ] && . "$TASKCFGDIR"/bfstart
|
[ -s "$TASKCFGDIR"/bfstart ] && . "$TASKCFGDIR"/bfstart
|
||||||
#检查内核配置文件
|
#检查内核配置文件
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ prepare_clash_base_config() {
|
|||||||
external="external-controller: 0.0.0.0:$db_port"
|
external="external-controller: 0.0.0.0:$db_port"
|
||||||
if [ "$redir_mod" = "Mix" -o "$redir_mod" = "Tun" ]; then
|
if [ "$redir_mod" = "Mix" -o "$redir_mod" = "Tun" ]; then
|
||||||
[ "$crashcore" = 'meta' ] && tun_meta=', device: utun, auto-route: false, auto-detect-interface: false'
|
[ "$crashcore" = 'meta' ] && tun_meta=', device: utun, auto-route: false, auto-detect-interface: false'
|
||||||
tun="tun: {enable: true, stack: system$tun_meta}"
|
tun="tun: {enable: true, stack: mips$tun_meta}"
|
||||||
else
|
else
|
||||||
tun='tun: {enable: false}'
|
tun='tun: {enable: false}'
|
||||||
fi
|
fi
|
||||||
@@ -37,8 +37,8 @@ dns:
|
|||||||
default-nameserver: [ $dns_resolver ]
|
default-nameserver: [ $dns_resolver ]
|
||||||
direct-nameserver: [ $dns_nameserver ]
|
direct-nameserver: [ $dns_nameserver ]
|
||||||
enhanced-mode: fake-ip
|
enhanced-mode: fake-ip
|
||||||
fake-ip-range: 198.18.0.0/15
|
fake-ip-range: $fakeip4
|
||||||
fake-ip-range6: fc00::/16
|
fake-ip-range6: $fakeip6
|
||||||
fake-ip-filter:
|
fake-ip-filter:
|
||||||
EOF
|
EOF
|
||||||
if [ "$dns_mod" = "mix" ] || [ "$dns_mod" = "fake-ip" ]; then
|
if [ "$dns_mod" = "mix" ] || [ "$dns_mod" = "fake-ip" ]; then
|
||||||
@@ -48,12 +48,27 @@ EOF
|
|||||||
fi
|
fi
|
||||||
#mix模式fakeip绕过cn
|
#mix模式fakeip绕过cn
|
||||||
[ "$dns_mod" = "mix" ] && echo ' - "rule-set:cn"' >>"$TMPDIR"/dns.yaml
|
[ "$dns_mod" = "mix" ] && echo ' - "rule-set:cn"' >>"$TMPDIR"/dns.yaml
|
||||||
|
#mix和route模式插入用户自定义直连域名
|
||||||
|
if [ "$dns_mod" = "mix" ] || [ "$dns_mod" = "route" ]; then
|
||||||
|
if [ -s "$CRASHDIR/configs/dns_direct_domains" ]; then
|
||||||
|
cat "$CRASHDIR/configs/dns_direct_domains" | grep -v '^#' | sed "s/^/ - '/" | sed "s/$/'/" >>"$TMPDIR"/dns.yaml
|
||||||
|
fi
|
||||||
|
fi
|
||||||
#mix模式和route模式插入分流设置
|
#mix模式和route模式插入分流设置
|
||||||
if [ "$dns_mod" = "mix" ] || [ "$dns_mod" = "route" ]; then
|
if [ "$dns_mod" = "mix" ] || [ "$dns_mod" = "route" ]; then
|
||||||
[ "$dns_protect" != "OFF" ] && dns_final="$dns_fallback" || dns_final="$dns_nameserver"
|
[ "$dns_protect" != "OFF" ] && dns_final="$dns_fallback" || dns_final="$dns_nameserver"
|
||||||
|
# 构建nameserver-policy
|
||||||
|
echo " respect-rules: true" >>"$TMPDIR"/dns.yaml
|
||||||
|
echo " nameserver-policy:" >>"$TMPDIR"/dns.yaml
|
||||||
|
# 添加用户自定义直连域名
|
||||||
|
if [ -s "$CRASHDIR/configs/dns_direct_domains" ]; then
|
||||||
|
cat "$CRASHDIR/configs/dns_direct_domains" | grep -v '^#' | while read domain; do
|
||||||
|
[ -n "$domain" ] && echo " '$domain': [ $dns_nameserver ]" >>"$TMPDIR"/dns.yaml
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
# 添加CN规则集
|
||||||
|
echo " 'rule-set:cn': [ $dns_nameserver ]" >>"$TMPDIR"/dns.yaml
|
||||||
cat >>"$TMPDIR"/dns.yaml <<EOF
|
cat >>"$TMPDIR"/dns.yaml <<EOF
|
||||||
respect-rules: true
|
|
||||||
nameserver-policy: {'rule-set:cn': [ $dns_nameserver ]}
|
|
||||||
proxy-server-nameserver : [ $dns_proxy_server ]
|
proxy-server-nameserver : [ $dns_proxy_server ]
|
||||||
nameserver: [ $dns_final ]
|
nameserver: [ $dns_final ]
|
||||||
EOF
|
EOF
|
||||||
@@ -205,6 +220,25 @@ add_custom_inbounds_and_rules() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
preserve_geodata_yaml() {
|
||||||
|
#保留订阅规则依赖的Geo数据设置,本地自定义同名配置优先
|
||||||
|
: >"$TMPDIR"/geodata_base.yaml
|
||||||
|
: >"$TMPDIR"/geodata.yaml
|
||||||
|
for char in geodata-mode geodata-loader geosite-matcher geo-auto-update geo-update-interval geox-url; do
|
||||||
|
awk -v key="$char" '
|
||||||
|
/^[^[:space:]#]/ { emit = ($0 ~ ("^" key ":")) }
|
||||||
|
emit { print }
|
||||||
|
' "$core_config" >>"$TMPDIR"/geodata_base.yaml
|
||||||
|
done
|
||||||
|
for char in geodata-mode geodata-loader geosite-matcher geo-auto-update geo-update-interval geox-url; do
|
||||||
|
grep -qE "^$char:" "$CRASHDIR"/yamls/user.yaml "$CRASHDIR"/yamls/others.yaml 2>/dev/null && continue
|
||||||
|
awk -v key="$char" '
|
||||||
|
/^[^[:space:]#]/ { emit = ($0 ~ ("^" key ":")) }
|
||||||
|
emit { print }
|
||||||
|
' "$TMPDIR"/geodata_base.yaml >>"$TMPDIR"/geodata.yaml
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
merger_yaml() {
|
merger_yaml() {
|
||||||
#mix和route模式生成rule-providers
|
#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 && {
|
[ "$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 && {
|
||||||
@@ -233,8 +267,9 @@ merger_yaml() {
|
|||||||
yaml_add="$yaml_add $TMPDIR/${char}.yaml"
|
yaml_add="$yaml_add $TMPDIR/${char}.yaml"
|
||||||
}
|
}
|
||||||
done
|
done
|
||||||
|
preserve_geodata_yaml
|
||||||
#合并完整配置文件
|
#合并完整配置文件
|
||||||
cut -c 1- "$TMPDIR"/set.yaml $yaml_dns $yaml_hosts $yaml_user $yaml_others $yaml_add >"$TMPDIR"/config.yaml
|
cut -c 1- "$TMPDIR"/set.yaml "$TMPDIR"/geodata.yaml $yaml_dns $yaml_hosts $yaml_user $yaml_others $yaml_add >"$TMPDIR"/config.yaml
|
||||||
}
|
}
|
||||||
|
|
||||||
test_yaml() {
|
test_yaml() {
|
||||||
@@ -248,7 +283,7 @@ test_yaml() {
|
|||||||
sed -i "/#自定义策略组开始/,/#自定义策略组结束/d" "$TMPDIR"/proxy-groups.yaml
|
sed -i "/#自定义策略组开始/,/#自定义策略组结束/d" "$TMPDIR"/proxy-groups.yaml
|
||||||
mv -f "$TMPDIR"/set_bak.yaml "$TMPDIR"/set.yaml >/dev/null 2>&1
|
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
|
cut -c 1- "$TMPDIR"/set.yaml "$TMPDIR"/geodata_base.yaml $yaml_dns $yaml_add >"$TMPDIR"/config.yaml
|
||||||
sed -i "/#自定义/d" "$TMPDIR"/config.yaml
|
sed -i "/#自定义/d" "$TMPDIR"/config.yaml
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@@ -257,7 +292,7 @@ finalize_clash_yaml() {
|
|||||||
#建立软连接
|
#建立软连接
|
||||||
[ ""$TMPDIR"" = ""$BINDIR"" ] || ln -sf "$TMPDIR"/config.yaml "$BINDIR"/config.yaml 2>/dev/null || cp -f "$TMPDIR"/config.yaml "$BINDIR"/config.yaml
|
[ ""$TMPDIR"" = ""$BINDIR"" ] || ln -sf "$TMPDIR"/config.yaml "$BINDIR"/config.yaml 2>/dev/null || cp -f "$TMPDIR"/config.yaml "$BINDIR"/config.yaml
|
||||||
#清理缓存
|
#清理缓存
|
||||||
for char in $yaml_char set set_bak dns hosts; do
|
for char in $yaml_char set set_bak dns hosts geodata geodata_base; do
|
||||||
rm -f "$TMPDIR"/${char}.yaml
|
rm -f "$TMPDIR"/${char}.yaml
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|||||||
+158
-21
@@ -1,34 +1,171 @@
|
|||||||
|
ipv6_route_prefixes() {
|
||||||
|
awk '
|
||||||
|
function is_global_prefix(value) {
|
||||||
|
return value ~ /^[23][0-9A-Fa-f]*:/ && value ~ /\/[0-9]+$/
|
||||||
|
}
|
||||||
|
$1 == "default" {
|
||||||
|
for (i = 1; i < NF; i++) {
|
||||||
|
if ($i == "from" && is_global_prefix($(i + 1)))
|
||||||
|
print $(i + 1)
|
||||||
|
}
|
||||||
|
next
|
||||||
|
}
|
||||||
|
is_global_prefix($1) {
|
||||||
|
via = 0
|
||||||
|
for (i = 1; i <= NF; i++) {
|
||||||
|
if ($i == "via")
|
||||||
|
via = 1
|
||||||
|
}
|
||||||
|
if (!via)
|
||||||
|
print $1
|
||||||
|
}'
|
||||||
|
}
|
||||||
|
|
||||||
|
get_lan_ifaces() {
|
||||||
|
ip route show scope link 2>/dev/null |
|
||||||
|
grep -Ev 'default|ppp|wan|utun|iot|peer|docker|podman|virbr|vnet|ovs|vmbr|veth|vmnic|vboxnet|lxcbr|xenbr|vEthernet|wgs|multicast|anycast' |
|
||||||
|
awk '{for(i=1;i<=NF;i++) if($i=="dev") {print $(i+1); break}}' |
|
||||||
|
grep -v '^lo$' |
|
||||||
|
sort -u
|
||||||
|
}
|
||||||
|
|
||||||
|
get_openwrt_lan_ifaces() {
|
||||||
|
if command -v ubus >/dev/null 2>&1; then
|
||||||
|
ubus -S call network.interface.lan status 2>/dev/null |
|
||||||
|
awk -F '"' '$2 == "l3_device" {print $4}'
|
||||||
|
fi
|
||||||
|
printf '%s\n' $lan_ifaces
|
||||||
|
}
|
||||||
|
|
||||||
|
get_ipv6_prefixes_openwrt() {
|
||||||
|
ipv6_prefixes=$(
|
||||||
|
for ipv6_iface in $(get_openwrt_lan_ifaces | sort -u); do
|
||||||
|
ip -6 route show dev "$ipv6_iface" 2>/dev/null |
|
||||||
|
grep -v '^default' |
|
||||||
|
ipv6_route_prefixes
|
||||||
|
done
|
||||||
|
)
|
||||||
|
# Some OpenWrt variants do not expose the LAN route through BusyBox ip.
|
||||||
|
# In that case, use netifd's source-specific default route as a fallback.
|
||||||
|
[ -n "$ipv6_prefixes" ] || ipv6_prefixes=$(
|
||||||
|
ip -6 route show default 2>/dev/null | ipv6_route_prefixes
|
||||||
|
)
|
||||||
|
printf '%s\n' "$ipv6_prefixes" | sort -u
|
||||||
|
}
|
||||||
|
|
||||||
|
get_ipv6_prefixes_linux() {
|
||||||
|
ipv6_prefixes=$(
|
||||||
|
for ipv6_iface in $lan_ifaces; do
|
||||||
|
ip -6 route show dev "$ipv6_iface" 2>/dev/null | grep -v '^default'
|
||||||
|
done | ipv6_route_prefixes | sort -u
|
||||||
|
)
|
||||||
|
# A host may use one interface for both its uplink and LAN, or may not
|
||||||
|
# have an IPv4 LAN route. Fall back to directly connected global routes.
|
||||||
|
[ -n "$ipv6_prefixes" ] || ipv6_prefixes=$(
|
||||||
|
ip -6 route show 2>/dev/null |
|
||||||
|
grep -Ev 'unreachable|prohibit|blackhole|ppp|wan|utun|iot|peer|docker|podman|virbr|vnet|ovs|vmbr|veth|vmnic|vboxnet|lxcbr|xenbr|vEthernet|wgs|multicast|anycast' |
|
||||||
|
ipv6_route_prefixes |
|
||||||
|
sort -u
|
||||||
|
)
|
||||||
|
printf '%s\n' "$ipv6_prefixes"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_ipv6_prefixes_router() {
|
||||||
|
# Padavan/Asuswrt and other BusyBox based firmware do not consistently
|
||||||
|
# expose route protocol metadata. Only depend on route shape and devices.
|
||||||
|
ipv6_prefixes=$(
|
||||||
|
for ipv6_iface in $lan_ifaces; do
|
||||||
|
ip -6 route show dev "$ipv6_iface" 2>/dev/null |
|
||||||
|
grep -v '^default' |
|
||||||
|
ipv6_route_prefixes
|
||||||
|
done
|
||||||
|
)
|
||||||
|
[ -n "$ipv6_prefixes" ] || ipv6_prefixes=$(
|
||||||
|
ip -6 route show default 2>/dev/null | ipv6_route_prefixes
|
||||||
|
)
|
||||||
|
printf '%s\n' "$ipv6_prefixes" | sort -u
|
||||||
|
}
|
||||||
|
|
||||||
|
get_ipv6_prefixes_fallback() {
|
||||||
|
# Generic fallback for systems unknown to ShellCrash. Avoid fixed field
|
||||||
|
# positions and route protocol names, which differ across ip variants.
|
||||||
|
ip -6 route show 2>/dev/null | ipv6_route_prefixes | sort -u
|
||||||
|
}
|
||||||
|
|
||||||
|
get_ipv6_platform() {
|
||||||
|
case "$systype" in
|
||||||
|
mi_snapshot | ng_snapshot)
|
||||||
|
echo openwrt
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
Padavan | asusrouter)
|
||||||
|
echo router
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
container)
|
||||||
|
echo linux
|
||||||
|
return
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -f /etc/openwrt_release ] || { [ -f /etc/rc.common ] && command -v uci >/dev/null 2>&1; }; then
|
||||||
|
echo openwrt
|
||||||
|
elif [ "$(uname -s 2>/dev/null)" = Linux ]; then
|
||||||
|
echo linux
|
||||||
|
else
|
||||||
|
echo fallback
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
get_ipv6_prefixes() {
|
||||||
|
[ -n "$lan_ifaces" ] || lan_ifaces=$(get_lan_ifaces)
|
||||||
|
case "$(get_ipv6_platform)" in
|
||||||
|
openwrt) get_ipv6_prefixes_openwrt ;;
|
||||||
|
router) get_ipv6_prefixes_router ;;
|
||||||
|
linux) get_ipv6_prefixes_linux ;;
|
||||||
|
*) get_ipv6_prefixes_fallback ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
build_host_ipv6() {
|
||||||
|
host_ipv6="fe80::/10 fd00::/8 $1"
|
||||||
|
[ "$ts_service" = ON ] && host_ipv6="$host_ipv6 fd7a:115c:a1e0::/48"
|
||||||
|
if [ "$wg_service" = ON ]; then
|
||||||
|
[ -f "$CRASHDIR"/configs/gateway.cfg ] && . "$CRASHDIR"/configs/gateway.cfg
|
||||||
|
[ -n "$wg_ipv6" ] && host_ipv6="$host_ipv6 $wg_ipv6"
|
||||||
|
fi
|
||||||
|
# Only pass prefix-shaped values to firewall generators and keep the
|
||||||
|
# result stable so the watcher can compare it cheaply.
|
||||||
|
host_ipv6=$(printf '%s\n' "$host_ipv6" |
|
||||||
|
tr ' ' '\n' |
|
||||||
|
awk '/^[0-9A-Fa-f:]+\/[0-9]+$/ {print}' |
|
||||||
|
sort -u |
|
||||||
|
tr '\n' ' ' |
|
||||||
|
sed 's/ $//')
|
||||||
|
}
|
||||||
|
|
||||||
getlanip() { #获取局域网host地址
|
getlanip() { #获取局域网host地址
|
||||||
i=1
|
i=1
|
||||||
while [ "$i" -le "20" ]; do
|
while [ "$i" -le "20" ]; do
|
||||||
#ipv4局域网网段
|
#ipv4局域网网段
|
||||||
host_ipv4=$(ip route show scope link | grep -Ev 'default|wan|utun|iot|peer|docker|podman|virbr|vnet|ovs|vmbr|veth|vmnic|vboxnet|lxcbr|xenbr|vEthernet|wgs|multicast|anycast' | awk '{print $1}')
|
host_ipv4=$(ip route show scope link | grep -Ev 'default|wan|utun|iot|peer|docker|podman|virbr|vnet|ovs|vmbr|veth|vmnic|vboxnet|lxcbr|xenbr|vEthernet|wgs|multicast|anycast' | awk '{print $1}')
|
||||||
#ipv6局域网网段 - 从IPv4已识别的LAN接口获取全局IPv6前缀
|
#ipv6局域网网段
|
||||||
[ "$ipv6_redir" = "ON" ] && {
|
if [ "$ipv6_redir" = "ON" ]; then
|
||||||
lan_ifaces=$(ip route show scope link | grep -Ev 'ppp|wan|utun|iot|peer|docker|podman|virbr|vnet|ovs|vmbr|veth|vmnic|vboxnet|lxcbr|xenbr|vEthernet|wgs|multicast|anycast' | awk '{for(i=1;i<=NF;i++) if($i=="dev") {print $(i+1); break}}' | grep -v '^lo$' | sort -u)
|
lan_ifaces=$(get_lan_ifaces)
|
||||||
host_ipv6=$(
|
detected_host_ipv6=$(get_ipv6_prefixes)
|
||||||
for iface in $lan_ifaces; do
|
fi
|
||||||
ip -6 addr show dev $iface 2>/dev/null
|
|
||||||
done | grep 'scope global' | awk '{print $2}' | tr '\n' ' ' | sed 's/ $//'
|
|
||||||
)
|
|
||||||
[ -z "$host_ipv6" ] && host_ipv6=$(ip -6 route show | grep -Ev 'default|unreachable|fe80::/|wan|ppp|utun|iot|peer|docker|podman|virbr|vnet|ovs|vmbr|veth|vmnic|vboxnet|lxcbr|xenbr|vEthernet|wgs|multicast|anycast' | awk '{print $1}' | tr '\n' ' ' | sed 's/ $//')
|
|
||||||
}
|
|
||||||
[ -f "$TMPDIR"/ShellCrash.log ] && break
|
[ -f "$TMPDIR"/ShellCrash.log ] && break
|
||||||
[ -n "$host_ipv4" -a "$ipv6_redir" != "ON" ] && break
|
[ -n "$host_ipv4" ] && [ "$ipv6_redir" != "ON" ] && break
|
||||||
[ -n "$host_ipv4" -a -n "$host_ipv6" ] && break
|
[ -n "$host_ipv4" ] && [ -n "$detected_host_ipv6" ] && break
|
||||||
sleep 1 && i=$((i + 1))
|
sleep 1 && i=$((i + 1))
|
||||||
done
|
done
|
||||||
#Tailscale
|
#Tailscale
|
||||||
[ "$ts_service" = ON ] && {
|
[ "$ts_service" = ON ] && ts_host_ipv4=' 100.64.0.0/10'
|
||||||
ts_host_ipv4=' 100.64.0.0/10'
|
|
||||||
ts_host_ipv6=' fd7a:115c:a1e0::/48'
|
|
||||||
}
|
|
||||||
#Wireguard
|
#Wireguard
|
||||||
[ "$wg_service" = ON ] && {
|
if [ "$wg_service" = ON ]; then
|
||||||
. "$CRASHDIR"/configs/gateway.cfg
|
. "$CRASHDIR"/configs/gateway.cfg
|
||||||
wg_host_ipv4=' $wg_ipv4'
|
wg_host_ipv4=" $wg_ipv4"
|
||||||
[ -n "$wg_ipv6" ] && wg_host_ipv6=' $wg_ipv6'
|
fi
|
||||||
}
|
|
||||||
#添加自定义ipv4局域网网段
|
#添加自定义ipv4局域网网段
|
||||||
if [ "$replace_default_host_ipv4" = "ON" ]; then
|
if [ "$replace_default_host_ipv4" = "ON" ]; then
|
||||||
host_ipv4="$cust_host_ipv4"
|
host_ipv4="$cust_host_ipv4"
|
||||||
@@ -40,7 +177,7 @@ getlanip() { #获取局域网host地址
|
|||||||
host_ipv4='192.168.0.0/16 10.0.0.0/12 172.16.0.0/12'
|
host_ipv4='192.168.0.0/16 10.0.0.0/12 172.16.0.0/12'
|
||||||
logger "无法获取本地LAN-IPV4网段,请前往流量过滤设置界面设置自定义网段!" 31
|
logger "无法获取本地LAN-IPV4网段,请前往流量过滤设置界面设置自定义网段!" 31
|
||||||
}
|
}
|
||||||
host_ipv6="fe80::/10 fd00::/8 $host_ipv6$ts_host_ipv6$wg_host_ipv6"
|
build_host_ipv6 "$detected_host_ipv6"
|
||||||
#获取本机出口IP地址
|
#获取本机出口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)
|
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 "$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)
|
||||||
|
|||||||
@@ -88,8 +88,8 @@ start_ipt_route() { #iptables-route通用工具
|
|||||||
else
|
else
|
||||||
"$1" $w -t "$2" -I "$3" -p "$5" -j "$4"
|
"$1" $w -t "$2" -I "$3" -p "$5" -j "$4"
|
||||||
fi
|
fi
|
||||||
[ "$dns_mod" = "mix" -o "$dns_mod" = "fake-ip" ] && [ "$common_ports" = "ON" ] && [ "$1" = iptables ] && "$1" $w -t "$2" -I "$3" -p "$5" -d 198.18.0.0/15 -j "$4"
|
[ "$dns_mod" = "mix" -o "$dns_mod" = "fake-ip" ] && [ "$common_ports" = "ON" ] && [ "$1" = iptables ] && "$1" $w -t "$2" -I "$3" -p "$5" -d $fakeip4 -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"
|
[ "$dns_mod" = "mix" -o "$dns_mod" = "fake-ip" ] && [ "$common_ports" = "ON" ] && [ "$1" = ip6tables ] && "$1" $w -t "$2" -I "$3" -p "$5" -d $fakeip6 -j "$4"
|
||||||
}
|
}
|
||||||
[ "$5" = "tcp" -o "$5" = "all" ] && proxy_set "$1" "$2" "$3" "$4" tcp
|
[ "$5" = "tcp" -o "$5" = "all" ] && proxy_set "$1" "$2" "$3" "$4" tcp
|
||||||
[ "$5" = "udp" -o "$5" = "all" ] && proxy_set "$1" "$2" "$3" "$4" udp
|
[ "$5" = "udp" -o "$5" = "all" ] && proxy_set "$1" "$2" "$3" "$4" udp
|
||||||
|
|||||||
Executable
+123
@@ -0,0 +1,123 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Keep the nftables LAN IPv6 prefix set in sync with dynamic prefixes.
|
||||||
|
|
||||||
|
[ -z "$CRASHDIR" ] && CRASHDIR=$(
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
cd ..
|
||||||
|
pwd
|
||||||
|
)
|
||||||
|
. "$CRASHDIR"/libs/get_config.sh
|
||||||
|
. "$CRASHDIR"/starts/fw_getlanip.sh
|
||||||
|
|
||||||
|
[ -z "$TMPDIR" ] && TMPDIR=/tmp/ShellCrash
|
||||||
|
ipv6_watch_pid="$TMPDIR/ipv6_watch.pid"
|
||||||
|
ipv6_watch_fifo="$TMPDIR/ipv6_route_monitor.$$"
|
||||||
|
ipv6_nft_family=${SHELLCRASH_NFT_FAMILY:-inet}
|
||||||
|
ipv6_nft_table=${SHELLCRASH_NFT_TABLE:-shellcrash}
|
||||||
|
ipv6_nft_set=${SHELLCRASH_IPV6_SET:-lan_ip6}
|
||||||
|
|
||||||
|
stop_ipv6_watch() {
|
||||||
|
[ -s "$ipv6_watch_pid" ] || return 0
|
||||||
|
ipv6_watch_old_pid=$(cat "$ipv6_watch_pid" 2>/dev/null)
|
||||||
|
case "$ipv6_watch_old_pid" in
|
||||||
|
'' | *[!0-9]*) ;;
|
||||||
|
*)
|
||||||
|
if [ ! -r "/proc/$ipv6_watch_old_pid/cmdline" ] ||
|
||||||
|
tr '\0' ' ' <"/proc/$ipv6_watch_old_pid/cmdline" 2>/dev/null | grep -q 'fw_ipv6_watch.sh'; then
|
||||||
|
kill "$ipv6_watch_old_pid" 2>/dev/null
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
rm -f "$ipv6_watch_pid"
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup_ipv6_watch() {
|
||||||
|
trap - EXIT INT TERM
|
||||||
|
[ -n "$ipv6_monitor_pid" ] && kill "$ipv6_monitor_pid" 2>/dev/null
|
||||||
|
[ -p "$ipv6_watch_fifo" ] && rm -f "$ipv6_watch_fifo"
|
||||||
|
if [ "$(cat "$ipv6_watch_pid" 2>/dev/null)" = "$$" ]; then
|
||||||
|
rm -f "$ipv6_watch_pid"
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
update_ipv6_set() {
|
||||||
|
lan_ifaces=$(get_lan_ifaces)
|
||||||
|
detected_host_ipv6=$(get_ipv6_prefixes)
|
||||||
|
build_host_ipv6 "$detected_host_ipv6"
|
||||||
|
ipv6_watch_state="$host_ipv6"
|
||||||
|
|
||||||
|
if [ "$ipv6_watch_state" = "$ipv6_watch_last_state" ] &&
|
||||||
|
nft list set "$ipv6_nft_family" "$ipv6_nft_table" "$ipv6_nft_set" >/dev/null 2>&1; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
ipv6_watch_elements=$(echo "$host_ipv6" | sed 's/[[:space:]]\+/, /g')
|
||||||
|
[ -n "$ipv6_watch_elements" ] || return 1
|
||||||
|
nft list set "$ipv6_nft_family" "$ipv6_nft_table" "$ipv6_nft_set" >/dev/null 2>&1 || return 1
|
||||||
|
|
||||||
|
# nft processes a batch atomically, so packets never observe a partially
|
||||||
|
# updated set while an ISP prefix is being replaced.
|
||||||
|
printf 'flush set %s %s %s\nadd element %s %s %s { %s }\n' \
|
||||||
|
"$ipv6_nft_family" "$ipv6_nft_table" "$ipv6_nft_set" \
|
||||||
|
"$ipv6_nft_family" "$ipv6_nft_table" "$ipv6_nft_set" "$ipv6_watch_elements" |
|
||||||
|
nft -f - >/dev/null 2>&1 || return 1
|
||||||
|
ipv6_watch_last_state="$ipv6_watch_state"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_iproute2_monitor() {
|
||||||
|
rm -f "$ipv6_watch_fifo"
|
||||||
|
mkfifo "$ipv6_watch_fifo" 2>/dev/null || return 1
|
||||||
|
ip -6 monitor route >"$ipv6_watch_fifo" 2>/dev/null &
|
||||||
|
ipv6_monitor_pid=$!
|
||||||
|
while IFS= read -r _ipv6_route_event; do
|
||||||
|
# Coalesce delete/add notifications emitted during renumbering.
|
||||||
|
sleep 1
|
||||||
|
update_ipv6_set
|
||||||
|
done <"$ipv6_watch_fifo"
|
||||||
|
wait "$ipv6_monitor_pid" 2>/dev/null
|
||||||
|
ipv6_monitor_pid=
|
||||||
|
rm -f "$ipv6_watch_fifo"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
run_ipv6_watch() {
|
||||||
|
mkdir -p "$TMPDIR"
|
||||||
|
echo $$ >"$ipv6_watch_pid"
|
||||||
|
trap cleanup_ipv6_watch EXIT INT TERM
|
||||||
|
ipv6_watch_last_state=
|
||||||
|
update_ipv6_set
|
||||||
|
|
||||||
|
# Full iproute2 has event monitoring. BusyBox/router variants that do not
|
||||||
|
# support it use a small polling fallback instead.
|
||||||
|
if ip -Version 2>&1 | grep -qi 'iproute2'; then
|
||||||
|
run_iproute2_monitor
|
||||||
|
fi
|
||||||
|
while :; do
|
||||||
|
sleep 30
|
||||||
|
update_ipv6_set
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
mkdir -p "$TMPDIR"
|
||||||
|
stop_ipv6_watch
|
||||||
|
/bin/sh "$0" run >/dev/null 2>&1 &
|
||||||
|
echo $! >"$ipv6_watch_pid"
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
stop_ipv6_watch
|
||||||
|
;;
|
||||||
|
run)
|
||||||
|
run_ipv6_watch
|
||||||
|
;;
|
||||||
|
once)
|
||||||
|
ipv6_watch_last_state=
|
||||||
|
update_ipv6_set
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: $0 {start|stop|run|once}" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -2,13 +2,22 @@
|
|||||||
# Copyright (C) Juewuy
|
# Copyright (C) Juewuy
|
||||||
|
|
||||||
RESERVED_IP=$(echo $reserve_ipv4 | sed 's/[[:space:]]\+/, /g')
|
RESERVED_IP=$(echo $reserve_ipv4 | sed 's/[[:space:]]\+/, /g')
|
||||||
RESERVED_IP6=$(echo "$reserve_ipv6 $host_ipv6" | sed 's/[[:space:]]\+/, /g')
|
RESERVED_IP6=$(echo "$reserve_ipv6" | sed 's/[[:space:]]\+/, /g')
|
||||||
|
|
||||||
|
start_nft_ipv6_set() {
|
||||||
|
HOST_IP6=$(echo "$host_ipv6" | sed 's/[[:space:]]\+/, /g')
|
||||||
|
nft list set inet shellcrash lan_ip6 >/dev/null 2>&1 ||
|
||||||
|
nft add set inet shellcrash lan_ip6 { type ipv6_addr \; flags interval \; auto-merge \; }
|
||||||
|
nft flush set inet shellcrash lan_ip6 2>/dev/null
|
||||||
|
[ -n "$HOST_IP6" ] && nft add element inet shellcrash lan_ip6 { $HOST_IP6 }
|
||||||
|
}
|
||||||
|
|
||||||
add_ip6_route(){
|
add_ip6_route(){
|
||||||
#过滤保留地址及本机地址
|
#过滤保留地址及当前局域网地址
|
||||||
nft add rule inet shellcrash $1 ip6 daddr {$RESERVED_IP6} return
|
nft add rule inet shellcrash $1 ip6 daddr {$RESERVED_IP6} return
|
||||||
#仅代理本机局域网网段流量
|
nft add rule inet shellcrash $1 ip6 daddr @lan_ip6 return
|
||||||
nft add rule inet shellcrash $1 ip6 saddr != {$HOST_IP6} return
|
#OUTPUT只包含本机流量,无需依赖动态公网源前缀
|
||||||
|
[ "$1" = 'prerouting' ] && nft add rule inet shellcrash $1 ip6 saddr != @lan_ip6 return
|
||||||
#绕过CN_IPV6
|
#绕过CN_IPV6
|
||||||
[ "$dns_mod" != "fake-ip" -a "$cn_ip_route" = "ON" -a -f "$BINDIR"/cn_ipv6.txt ] && {
|
[ "$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)
|
CN_IP6=$(awk '{printf "%s, ",$1}' "$BINDIR"/cn_ipv6.txt)
|
||||||
@@ -38,12 +47,12 @@ start_nft_route() { #nftables-route通用工具
|
|||||||
[ -z "$ports" ] && nft add rule inet shellcrash $1 tcp dport {"$mix_port, $redir_port, $tproxy_port"} return
|
[ -z "$ports" ] && nft add rule inet shellcrash $1 tcp dport {"$mix_port, $redir_port, $tproxy_port"} return
|
||||||
#过滤常用端口
|
#过滤常用端口
|
||||||
[ -n "$PORTS" ] && {
|
[ -n "$PORTS" ] && {
|
||||||
nft add rule inet shellcrash $1 ip daddr != {198.18.0.0/15} tcp dport != {$PORTS} return
|
nft add rule inet shellcrash $1 ip daddr != {$fakeip4} tcp dport != {$PORTS} return
|
||||||
nft add rule inet shellcrash $1 ip daddr != {198.18.0.0/15} udp dport != {$PORTS} return
|
nft add rule inet shellcrash $1 ip daddr != {$fakeip4} 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 != {$fakeip6} tcp dport != {$PORTS} return
|
||||||
nft add rule inet shellcrash $1 ip6 daddr != {fc00::/16} udp dport != {$PORTS} return
|
nft add rule inet shellcrash $1 ip6 daddr != {$fakeip6} udp dport != {$PORTS} return
|
||||||
}
|
}
|
||||||
#nft add rule inet shellcrash $1 ip saddr 198.18.0.0/15 return
|
#nft add rule inet shellcrash $1 ip saddr $fakeip4 return
|
||||||
nft add rule inet shellcrash $1 ip daddr {$RESERVED_IP} return #过滤保留地址
|
nft add rule inet shellcrash $1 ip daddr {$RESERVED_IP} return #过滤保留地址
|
||||||
#过滤局域网设备
|
#过滤局域网设备
|
||||||
[ "$1" = 'prerouting' ] && {
|
[ "$1" = 'prerouting' ] && {
|
||||||
@@ -83,10 +92,8 @@ start_nft_route() { #nftables-route通用工具
|
|||||||
}
|
}
|
||||||
#局域网ipv6支持
|
#局域网ipv6支持
|
||||||
if [ "$ipv6_redir" = "ON" -a "$1" = 'prerouting' -a "$firewall_area" != 5 ]; then
|
if [ "$ipv6_redir" = "ON" -a "$1" = 'prerouting' -a "$firewall_area" != 5 ]; then
|
||||||
HOST_IP6=$(echo $host_ipv6 | sed 's/[[:space:]]\+/, /g')
|
|
||||||
add_ip6_route "$1"
|
add_ip6_route "$1"
|
||||||
elif [ "$ipv6_redir" = "ON" -a "$1" = 'output' -a \( "$firewall_area" = 2 -o "$firewall_area" = 3 \) ]; then
|
elif [ "$ipv6_redir" = "ON" -a "$1" = 'output' -a \( "$firewall_area" = 2 -o "$firewall_area" = 3 \) ]; then
|
||||||
HOST_IP6="::1, $(echo $host_ipv6 | sed 's/[[:space:]]\+/, /g')"
|
|
||||||
add_ip6_route "$1"
|
add_ip6_route "$1"
|
||||||
else
|
else
|
||||||
nft add rule inet shellcrash $1 meta nfproto ipv6 return
|
nft add rule inet shellcrash $1 meta nfproto ipv6 return
|
||||||
@@ -106,7 +113,6 @@ start_nft_route() { #nftables-route通用工具
|
|||||||
start_nft_dns() { #nftables-dns
|
start_nft_dns() { #nftables-dns
|
||||||
[ "$1" = 'prerouting' ] && {
|
[ "$1" = 'prerouting' ] && {
|
||||||
HOST_IP=$(echo $host_ipv4 | sed 's/[[:space:]]\+/, /g')
|
HOST_IP=$(echo $host_ipv4 | sed 's/[[:space:]]\+/, /g')
|
||||||
HOST_IP6=$(echo $host_ipv6 | sed 's/[[:space:]]\+/, /g')
|
|
||||||
}
|
}
|
||||||
[ "$1" = 'output' ] && HOST_IP="127.0.0.0/8, $(echo $local_ipv4 | sed 's/[[:space:]]\+/, /g')"
|
[ "$1" = 'output' ] && HOST_IP="127.0.0.0/8, $(echo $local_ipv4 | sed 's/[[:space:]]\+/, /g')"
|
||||||
[ "$1" = 'prerouting_vm' ] && HOST_IP="$(echo $vm_ipv4 | sed 's/[[:space:]]\+/, /g')"
|
[ "$1" = 'prerouting_vm' ] && HOST_IP="$(echo $vm_ipv4 | sed 's/[[:space:]]\+/, /g')"
|
||||||
@@ -119,7 +125,7 @@ start_nft_dns() { #nftables-dns
|
|||||||
nft add rule inet shellcrash "$1"_dns meta skgid { 453, 7890 } 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
|
[ "$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 #屏蔽外部请求
|
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' ] && nft add rule inet shellcrash "$1"_dns ip6 saddr != @lan_ip6 return #屏蔽外部请求
|
||||||
#过滤局域网设备
|
#过滤局域网设备
|
||||||
[ "$1" = 'prerouting' ] && [ -s "$CRASHDIR"/configs/mac ] && {
|
[ "$1" = 'prerouting' ] && [ -s "$CRASHDIR"/configs/mac ] && {
|
||||||
MAC=$(awk '{printf "%s, ",$1}' "$CRASHDIR"/configs/mac)
|
MAC=$(awk '{printf "%s, ",$1}' "$CRASHDIR"/configs/mac)
|
||||||
@@ -134,7 +140,6 @@ start_nft_dns() { #nftables-dns
|
|||||||
}
|
}
|
||||||
start_nft_wan() { #nftables公网防火墙
|
start_nft_wan() { #nftables公网防火墙
|
||||||
HOST_IP=$(echo $host_ipv4 | sed 's/[[:space:]]\+/, /g')
|
HOST_IP=$(echo $host_ipv4 | sed 's/[[:space:]]\+/, /g')
|
||||||
HOST_IP6=$(echo $host_ipv6 | sed 's/[[:space:]]\+/, /g')
|
|
||||||
nft add chain inet shellcrash input { type filter hook input priority -100 \; }
|
nft add chain inet shellcrash input { type filter hook input priority -100 \; }
|
||||||
nft add rule inet shellcrash input iif lo accept #本机请求全放行
|
nft add rule inet shellcrash input iif lo accept #本机请求全放行
|
||||||
#端口放行
|
#端口放行
|
||||||
@@ -148,7 +153,7 @@ start_nft_wan() { #nftables公网防火墙
|
|||||||
#端口拦截
|
#端口拦截
|
||||||
reject_ports="{ $mix_port, $db_port }"
|
reject_ports="{ $mix_port, $db_port }"
|
||||||
nft add rule inet shellcrash input ip saddr {$HOST_IP} accept
|
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 ip6 saddr @lan_ip6 accept
|
||||||
nft add rule inet shellcrash input tcp dport $reject_ports reject
|
nft add rule inet shellcrash input tcp dport $reject_ports reject
|
||||||
nft add rule inet shellcrash input udp dport $reject_ports reject
|
nft add rule inet shellcrash input udp dport $reject_ports reject
|
||||||
#fw4特殊处理
|
#fw4特殊处理
|
||||||
@@ -160,6 +165,7 @@ start_nftables() { #nftables配置总入口
|
|||||||
#初始化nftables
|
#初始化nftables
|
||||||
nft add table inet shellcrash 2>/dev/null
|
nft add table inet shellcrash 2>/dev/null
|
||||||
nft flush table inet shellcrash 2>/dev/null
|
nft flush table inet shellcrash 2>/dev/null
|
||||||
|
start_nft_ipv6_set
|
||||||
#公网访问防火墙
|
#公网访问防火墙
|
||||||
[ "$fw_wan" != OFF ] && [ "$systype" != 'container' ] && start_nft_wan
|
[ "$fw_wan" != OFF ] && [ "$systype" != 'container' ] && start_nft_wan
|
||||||
#启动DNS劫持
|
#启动DNS劫持
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Copyright (C) Juewuy
|
# Copyright (C) Juewuy
|
||||||
|
|
||||||
|
#停止旧的IPv6前缀监听,避免防火墙重建期间并发更新
|
||||||
|
[ -f "$CRASHDIR"/starts/fw_ipv6_watch.sh ] && /bin/sh "$CRASHDIR"/starts/fw_ipv6_watch.sh stop
|
||||||
#获取局域网host地址
|
#获取局域网host地址
|
||||||
. "$CRASHDIR"/starts/fw_getlanip.sh && getlanip
|
. "$CRASHDIR"/starts/fw_getlanip.sh && getlanip
|
||||||
#缺省值
|
#缺省值
|
||||||
@@ -46,6 +48,9 @@
|
|||||||
#防火墙配置
|
#防火墙配置
|
||||||
[ "$firewall_mod" = 'iptables' ] && . "$CRASHDIR"/starts/fw_iptables.sh && start_iptables
|
[ "$firewall_mod" = 'iptables' ] && . "$CRASHDIR"/starts/fw_iptables.sh && start_iptables
|
||||||
[ "$firewall_mod" = 'nftables' ] && . "$CRASHDIR"/starts/fw_nftables.sh && start_nftables
|
[ "$firewall_mod" = 'nftables' ] && . "$CRASHDIR"/starts/fw_nftables.sh && start_nftables
|
||||||
|
#动态更新nftables中的IPv6局域网前缀集合
|
||||||
|
[ "$firewall_mod" = 'nftables' -a "$ipv6_redir" = "ON" ] &&
|
||||||
|
/bin/sh "$CRASHDIR"/starts/fw_ipv6_watch.sh start
|
||||||
#修复部分虚拟机dns查询失败的问题
|
#修复部分虚拟机dns查询失败的问题
|
||||||
[ "$firewall_area" = 2 -o "$firewall_area" = 3 ] && [ -z "$(grep '127.0.0.1' /etc/resolv.conf 2>/dev/null)" ] && [ "$systype" != 'container' ] && {
|
[ "$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}')
|
line=$(grep -n 'nameserver' /etc/resolv.conf | awk -F: 'FNR==1{print $1}')
|
||||||
|
|||||||
+15
-14
@@ -5,6 +5,8 @@
|
|||||||
[ -z "$CRASHDIR" ] && CRASHDIR=$( cd $(dirname $0);cd ..;pwd)
|
[ -z "$CRASHDIR" ] && CRASHDIR=$( cd $(dirname $0);cd ..;pwd)
|
||||||
. "$CRASHDIR"/libs/get_config.sh
|
. "$CRASHDIR"/libs/get_config.sh
|
||||||
. "$CRASHDIR"/libs/check_cmd.sh
|
. "$CRASHDIR"/libs/check_cmd.sh
|
||||||
|
#停止IPv6前缀监听
|
||||||
|
[ -f "$CRASHDIR"/starts/fw_ipv6_watch.sh ] && /bin/sh "$CRASHDIR"/starts/fw_ipv6_watch.sh stop
|
||||||
. "$CRASHDIR"/starts/fw_getlanip.sh && getlanip #获取局域网host地址
|
. "$CRASHDIR"/starts/fw_getlanip.sh && getlanip #获取局域网host地址
|
||||||
#缺省值
|
#缺省值
|
||||||
[ -z "$common_ports" ] && common_ports='ON'
|
[ -z "$common_ports" ] && common_ports='ON'
|
||||||
@@ -48,18 +50,18 @@ ckcmd iptables && {
|
|||||||
$iptable -t mangle -D OUTPUT -p udp -j shellcrash_mark_out 2>/dev/null
|
$iptable -t mangle -D OUTPUT -p udp -j shellcrash_mark_out 2>/dev/null
|
||||||
fi
|
fi
|
||||||
#redir
|
#redir
|
||||||
$iptable -t nat -D PREROUTING -p tcp -d 198.18.0.0/15 -j shellcrash 2>/dev/null
|
$iptable -t nat -D PREROUTING -p tcp -d $fakeip4 -j shellcrash 2>/dev/null
|
||||||
$iptable -t nat -D OUTPUT -p tcp -d 198.18.0.0/15 -j shellcrash_out 2>/dev/null
|
$iptable -t nat -D OUTPUT -p tcp -d $fakeip4 -j shellcrash_out 2>/dev/null
|
||||||
#vm_dns
|
#vm_dns
|
||||||
$iptable -t nat -D PREROUTING -p tcp --dport 53 -j shellcrash_vm_dns 2>/dev/null
|
$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
|
$iptable -t nat -D PREROUTING -p udp --dport 53 -j shellcrash_vm_dns 2>/dev/null
|
||||||
#vm_redir
|
#vm_redir
|
||||||
$iptable -t nat -D PREROUTING -p tcp -d 198.18.0.0/15 -j shellcrash_vm 2>/dev/null
|
$iptable -t nat -D PREROUTING -p tcp -d $fakeip4 -j shellcrash_vm 2>/dev/null
|
||||||
#TPROXY&tun
|
#TPROXY&tun
|
||||||
$iptable -t mangle -D PREROUTING -p tcp -d 198.18.0.0/15 -j shellcrash_mark 2>/dev/null
|
$iptable -t mangle -D PREROUTING -p tcp -d $fakeip4 -j shellcrash_mark 2>/dev/null
|
||||||
$iptable -t mangle -D PREROUTING -p udp -d 198.18.0.0/15 -j shellcrash_mark 2>/dev/null
|
$iptable -t mangle -D PREROUTING -p udp -d $fakeip4 -j shellcrash_mark 2>/dev/null
|
||||||
$iptable -t mangle -D OUTPUT -p tcp -d 198.18.0.0/15 -j shellcrash_mark_out 2>/dev/null
|
$iptable -t mangle -D OUTPUT -p tcp -d $fakeip4 -j shellcrash_mark_out 2>/dev/null
|
||||||
$iptable -t mangle -D OUTPUT -p udp -d 198.18.0.0/15 -j shellcrash_mark_out 2>/dev/null
|
$iptable -t mangle -D OUTPUT -p udp -d $fakeip4 -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 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
|
$iptable -t mangle -D PREROUTING -m mark --mark $fwmark -p udp -j TPROXY --on-port $tproxy_port 2>/dev/null
|
||||||
#tun
|
#tun
|
||||||
@@ -119,15 +121,15 @@ ckcmd ip6tables && {
|
|||||||
$ip6table -t mangle -D OUTPUT -p udp -j shellcrashv6_mark_out 2>/dev/null
|
$ip6table -t mangle -D OUTPUT -p udp -j shellcrashv6_mark_out 2>/dev/null
|
||||||
fi
|
fi
|
||||||
#redir
|
#redir
|
||||||
$ip6table -t nat -D PREROUTING -p tcp -d fc00::/16 -j shellcrashv6 2>/dev/null
|
$ip6table -t nat -D PREROUTING -p tcp -d $fakeip6 -j shellcrashv6 2>/dev/null
|
||||||
$ip6table -t nat -D OUTPUT -p tcp -d fc00::/16 -j shellcrashv6_out 2>/dev/null
|
$ip6table -t nat -D OUTPUT -p tcp -d $fakeip6 -j shellcrashv6_out 2>/dev/null
|
||||||
$ip6table -D INPUT -p tcp --dport 53 -j REJECT 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
|
$ip6table -D INPUT -p udp --dport 53 -j REJECT 2>/dev/null
|
||||||
#mark
|
#mark
|
||||||
$ip6table -t mangle -D PREROUTING -p tcp -d fc00::/16 -j shellcrashv6_mark 2>/dev/null
|
$ip6table -t mangle -D PREROUTING -p tcp -d $fakeip6 -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 PREROUTING -p udp -d $fakeip6 -j shellcrashv6_mark 2>/dev/null
|
||||||
$ip6table -t mangle -D OUTPUT -p tcp -d fc00::/16 -j shellcrashv6_mark_out 2>/dev/null
|
$ip6table -t mangle -D OUTPUT -p tcp -d $fakeip6 -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 -t mangle -D OUTPUT -p udp -d $fakeip6 -j shellcrashv6_mark_out 2>/dev/null
|
||||||
$ip6table -D INPUT -p udp --dport 443 $set_cn_ip -j REJECT 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 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
|
$ip6table -t mangle -D PREROUTING -m mark --mark $fwmark -p udp -j TPROXY --on-port $tproxy_port 2>/dev/null
|
||||||
@@ -172,4 +174,3 @@ 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
|
[ -s /etc/init.d/firewall.bak ] && mv -f /etc/init.d/firewall.bak /etc/init.d/firewall
|
||||||
#others
|
#others
|
||||||
sed -i '/shellcrash-dns-repair/d' /etc/resolv.conf 2>/dev/null
|
sed -i '/shellcrash-dns-repair/d' /etc/resolv.conf 2>/dev/null
|
||||||
|
|
||||||
|
|||||||
@@ -158,6 +158,15 @@ gen_dns() {
|
|||||||
[ -n "$fake_ip_filter_domain" ] && fake_ip_filter_domain="{ \"domain\": [$fake_ip_filter_domain], \"server\": \"dns_direct\" },"
|
[ -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_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\" },"
|
[ -n "$fake_ip_filter_regex" ] && fake_ip_filter_regex="{ \"domain_regex\": [$fake_ip_filter_regex], \"server\": \"dns_direct\" },"
|
||||||
|
# 用户自定义直连域名
|
||||||
|
if [ -s "$CRASHDIR/configs/dns_direct_domains" ]; then
|
||||||
|
custom_direct_domain=$(cat "$CRASHDIR/configs/dns_direct_domains" | grep -Ev '#|\*|\+' | sed '/^\s*$/d' | awk '{printf "\"%s\", ",$1}' | sed 's/, $//')
|
||||||
|
custom_direct_suffix=$(cat "$CRASHDIR/configs/dns_direct_domains" | grep '\*' | grep -v '.\*' | sed 's/\*\.//' | awk '{printf "\"%s\", ",$1}' | sed 's/, $//')
|
||||||
|
custom_direct_regex=$(cat "$CRASHDIR/configs/dns_direct_domains" | grep '.\*' | sed 's/\./\\\\./g' | sed 's/\*/.\*/' | awk '{printf "\"%s\", ",$1}' | sed 's/, $//')
|
||||||
|
[ -n "$custom_direct_domain" ] && custom_direct_domain_rule="{ \"domain\": [$custom_direct_domain], \"server\": \"dns_direct\" },"
|
||||||
|
[ -n "$custom_direct_suffix" ] && custom_direct_suffix_rule="{ \"domain_suffix\": [$custom_direct_suffix], \"server\": \"dns_direct\" },"
|
||||||
|
[ -n "$custom_direct_regex" ] && custom_direct_regex_rule="{ \"domain_regex\": [$custom_direct_regex], \"server\": \"dns_direct\" },"
|
||||||
|
fi
|
||||||
proxy_dns='{ "query_type": ["A", "AAAA"], "server": "dns_fakeip", "rewrite_ttl": 1 }'
|
proxy_dns='{ "query_type": ["A", "AAAA"], "server": "dns_fakeip", "rewrite_ttl": 1 }'
|
||||||
#mix模式插入fakeip过滤规则
|
#mix模式插入fakeip过滤规则
|
||||||
[ "$dns_mod" = "mix" ] && direct_dns='{ "rule_set": ["cn"], "server": "dns_direct" },'
|
[ "$dns_mod" = "mix" ] && direct_dns='{ "rule_set": ["cn"], "server": "dns_direct" },'
|
||||||
@@ -165,6 +174,15 @@ gen_dns() {
|
|||||||
[ "$dns_mod" = "route" ] && {
|
[ "$dns_mod" = "route" ] && {
|
||||||
global_dns=dns_proxy
|
global_dns=dns_proxy
|
||||||
direct_dns='{ "rule_set": ["cn"], "server": "dns_direct" }'
|
direct_dns='{ "rule_set": ["cn"], "server": "dns_direct" }'
|
||||||
|
# 用户自定义直连域名
|
||||||
|
if [ -s "$CRASHDIR/configs/dns_direct_domains" ]; then
|
||||||
|
custom_direct_domain=$(cat "$CRASHDIR/configs/dns_direct_domains" | grep -Ev '#|\*|\+' | sed '/^\s*$/d' | awk '{printf "\"%s\", ",$1}' | sed 's/, $//')
|
||||||
|
custom_direct_suffix=$(cat "$CRASHDIR/configs/dns_direct_domains" | grep '\*' | grep -v '.\*' | sed 's/\*\.//' | awk '{printf "\"%s\", ",$1}' | sed 's/, $//')
|
||||||
|
custom_direct_regex=$(cat "$CRASHDIR/configs/dns_direct_domains" | grep '.\*' | sed 's/\./\\\\./g' | sed 's/\*/.\*/' | awk '{printf "\"%s\", ",$1}' | sed 's/, $//')
|
||||||
|
[ -n "$custom_direct_domain" ] && custom_direct_domain_rule="{ \"domain\": [$custom_direct_domain], \"server\": \"dns_direct\" },"
|
||||||
|
[ -n "$custom_direct_suffix" ] && custom_direct_suffix_rule="{ \"domain_suffix\": [$custom_direct_suffix], \"server\": \"dns_direct\" },"
|
||||||
|
[ -n "$custom_direct_regex" ] && custom_direct_regex_rule="{ \"domain_regex\": [$custom_direct_regex], \"server\": \"dns_direct\" },"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
#防泄露设置
|
#防泄露设置
|
||||||
[ "$dns_protect" = "OFF" ] && sed -i 's/"server": "dns_proxy"/"server": "dns_direct"/g' "$TMPDIR"/jsons/route.json
|
[ "$dns_protect" = "OFF" ] && sed -i 's/"server": "dns_proxy"/"server": "dns_direct"/g' "$TMPDIR"/jsons/route.json
|
||||||
@@ -208,8 +226,8 @@ EOF
|
|||||||
{
|
{
|
||||||
"tag": "dns_fakeip",
|
"tag": "dns_fakeip",
|
||||||
"type": "fakeip",
|
"type": "fakeip",
|
||||||
"inet4_range": "198.18.0.0/15",
|
"inet4_range": "$fakeip4",
|
||||||
"inet6_range": "fc00::/16"
|
"inet6_range": "$fakeip6"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "dns_resolver",
|
"tag": "dns_resolver",
|
||||||
@@ -228,6 +246,9 @@ EOF
|
|||||||
$fake_ip_filter_domain
|
$fake_ip_filter_domain
|
||||||
$fake_ip_filter_suffix
|
$fake_ip_filter_suffix
|
||||||
$fake_ip_filter_regex
|
$fake_ip_filter_regex
|
||||||
|
$custom_direct_domain_rule
|
||||||
|
$custom_direct_suffix_rule
|
||||||
|
$custom_direct_regex_rule
|
||||||
{ "clash_mode": "Global", "query_type": ["A", "AAAA"], "server": "$global_dns", "rewrite_ttl": 1 },
|
{ "clash_mode": "Global", "query_type": ["A", "AAAA"], "server": "$global_dns", "rewrite_ttl": 1 },
|
||||||
$direct_dns
|
$direct_dns
|
||||||
$proxy_dns
|
$proxy_dns
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
CRASHDIR="$(uci get firewall.ShellCrash.path | sed 's/\/starts.*//')"
|
CRASHDIR="$(uci get firewall.ShellCrash.path | sed 's/\/starts.*//')"
|
||||||
#防止提前自启
|
#防止提前自启
|
||||||
/etc/init.d/shellcrash disable
|
/etc/init.d/shellcrash disable
|
||||||
crontab -l | grep -v 'start_legacy_wd.sh shellcrash' | crontab -
|
|
||||||
#防止usb未加载
|
#防止usb未加载
|
||||||
i=0
|
i=0
|
||||||
while [ ! -f "$CRASHDIR/configs/ShellCrash.cfg" ]; do
|
while [ ! -f "$CRASHDIR/configs/ShellCrash.cfg" ]; do
|
||||||
@@ -13,6 +12,8 @@ while [ ! -f "$CRASHDIR/configs/ShellCrash.cfg" ]; do
|
|||||||
sleep 3
|
sleep 3
|
||||||
done
|
done
|
||||||
. "$CRASHDIR"/configs/ShellCrash.cfg
|
. "$CRASHDIR"/configs/ShellCrash.cfg
|
||||||
|
. "$CRASHDIR"/libs/set_cron.sh
|
||||||
|
cronset 'start_legacy_wd.sh shellcrash' || exit 1
|
||||||
|
|
||||||
autoSSH() {
|
autoSSH() {
|
||||||
#自动开启SSH
|
#自动开启SSH
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Run with sh tests/clash_geodata.sh [path/to/clash_modify.sh].
|
||||||
|
set -e
|
||||||
|
script=${1:-$(dirname "$0")/../scripts/starts/clash_modify.sh}
|
||||||
|
. "$script"
|
||||||
|
test_dir=$(mktemp -d)
|
||||||
|
trap 'rm -rf "$test_dir"' EXIT HUP INT TERM
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
CRASHDIR="$test_dir/$1"
|
||||||
|
TMPDIR="$CRASHDIR/tmp"
|
||||||
|
BINDIR="$CRASHDIR/bin"
|
||||||
|
mkdir -p "$CRASHDIR/yamls" "$TMPDIR" "$BINDIR"
|
||||||
|
core_config="$CRASHDIR/yamls/config.yaml"
|
||||||
|
dns_mod=redir_host
|
||||||
|
yaml_char='rules proxy-groups'
|
||||||
|
yaml_user= yaml_others= yaml_dns= yaml_hosts=
|
||||||
|
printf 'mode: Rule\n' >"$TMPDIR/set.yaml"
|
||||||
|
printf ' - GEOSITE,GOOGLE,DIRECT\n' >"$TMPDIR/rules.yaml"
|
||||||
|
: >"$TMPDIR/proxy-groups.yaml"
|
||||||
|
cat >"$core_config" <<'EOF'
|
||||||
|
geodata-mode: true
|
||||||
|
geodata-loader: memconservative
|
||||||
|
geosite-matcher: succinct
|
||||||
|
geo-auto-update: true
|
||||||
|
geo-update-interval: 24
|
||||||
|
geox-url:
|
||||||
|
geoip: https://example.invalid/geoip.dat
|
||||||
|
geosite: >-
|
||||||
|
https://example.invalid/geosite.dat
|
||||||
|
mmdb: https://example.invalid/Country.mmdb
|
||||||
|
rules:
|
||||||
|
- GEOSITE,GOOGLE,DIRECT
|
||||||
|
mixed-port: 1234
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_line() {
|
||||||
|
grep -qFx -- "$1" "$TMPDIR/config.yaml" || {
|
||||||
|
echo "Missing expected line: $1" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setup inherited
|
||||||
|
merger_yaml
|
||||||
|
assert_line 'geodata-mode: true'
|
||||||
|
assert_line 'geodata-loader: memconservative'
|
||||||
|
assert_line 'geosite-matcher: succinct'
|
||||||
|
assert_line 'geo-auto-update: true'
|
||||||
|
assert_line 'geo-update-interval: 24'
|
||||||
|
assert_line ' https://example.invalid/geosite.dat'
|
||||||
|
[ "$(grep -c '^rules:' "$TMPDIR/config.yaml")" = 1 ]
|
||||||
|
! grep -q '^mixed-port: 1234' "$TMPDIR/config.yaml"
|
||||||
|
finalize_clash_yaml
|
||||||
|
[ ! -e "$TMPDIR/geodata.yaml" ]
|
||||||
|
[ ! -e "$TMPDIR/geodata_base.yaml" ]
|
||||||
|
|
||||||
|
setup overrides
|
||||||
|
printf 'geodata-mode: false\n' >"$CRASHDIR/yamls/user.yaml"
|
||||||
|
printf 'geox-url: {geosite: https://override.invalid/geosite.dat}\n' >"$CRASHDIR/yamls/others.yaml"
|
||||||
|
merger_yaml
|
||||||
|
assert_line 'geodata-mode: false'
|
||||||
|
assert_line 'geox-url: {geosite: https://override.invalid/geosite.dat}'
|
||||||
|
[ "$(grep -c '^geodata-mode:' "$TMPDIR/config.yaml")" = 1 ]
|
||||||
|
[ "$(grep -c '^geox-url:' "$TMPDIR/config.yaml")" = 1 ]
|
||||||
|
! grep -q 'example.invalid' "$TMPDIR/config.yaml"
|
||||||
|
|
||||||
|
# A rejected custom configuration must fall back to the subscription settings.
|
||||||
|
printf '#!/bin/sh\nexit 1\n' >"$TMPDIR/CrashCore"
|
||||||
|
chmod +x "$TMPDIR/CrashCore"
|
||||||
|
logger() { :; }
|
||||||
|
set +e
|
||||||
|
test_yaml
|
||||||
|
set -e
|
||||||
|
assert_line 'geodata-mode: true'
|
||||||
|
assert_line ' https://example.invalid/geosite.dat'
|
||||||
|
[ "$(grep -c '^geox-url:' "$TMPDIR/config.yaml")" = 1 ]
|
||||||
|
! grep -q 'override.invalid' "$TMPDIR/config.yaml"
|
||||||
|
|
||||||
|
setup inline
|
||||||
|
printf 'geox-url: {geosite: https://inline.invalid/geosite.dat}\ngeo-auto-update: false\n---\nmixed-port: 1234\n' >"$core_config"
|
||||||
|
merger_yaml
|
||||||
|
assert_line 'geox-url: {geosite: https://inline.invalid/geosite.dat}'
|
||||||
|
assert_line 'geo-auto-update: false'
|
||||||
|
! grep -qE '^---|^mixed-port: 1234' "$TMPDIR/config.yaml"
|
||||||
|
|
||||||
|
setup absent
|
||||||
|
printf 'rules:\n - MATCH,DIRECT\n' >"$core_config"
|
||||||
|
merger_yaml
|
||||||
|
! grep -qE '^geo(data|site|x|-)' "$TMPDIR/config.yaml"
|
||||||
|
assert_line 'mode: Rule'
|
||||||
|
echo 'PASS: inherited geodata, overrides, fallback, inline maps, cleanup and absent settings'
|
||||||
Executable
+83
@@ -0,0 +1,83 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
ROOT=$(cd "$(dirname "$0")/.." && pwd)
|
||||||
|
. "$ROOT/scripts/starts/fw_getlanip.sh"
|
||||||
|
|
||||||
|
assert_equal() {
|
||||||
|
if [ "$1" != "$2" ]; then
|
||||||
|
echo "expected: [$1]" >&2
|
||||||
|
echo "actual: [$2]" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
route_output='default via fe80::1 dev eth0
|
||||||
|
default from 240e:1234:5600::/56 via fe80::1 dev pppoe-wan
|
||||||
|
2408:8266:501:2443::/64 dev enp2s0 proto kernel
|
||||||
|
2606:4700::/48 via fe80::2 dev eth0
|
||||||
|
unreachable 240e:1234:5600::/48 dev lo'
|
||||||
|
actual=$(printf '%s\n' "$route_output" | ipv6_route_prefixes | sort -u)
|
||||||
|
expected='2408:8266:501:2443::/64
|
||||||
|
240e:1234:5600::/56'
|
||||||
|
assert_equal "$expected" "$actual"
|
||||||
|
|
||||||
|
# OpenWrt prefers the LAN assignment over the wider delegated prefix.
|
||||||
|
systype=mi_snapshot
|
||||||
|
lan_ifaces='br-lan'
|
||||||
|
ubus() {
|
||||||
|
printf '%s\n' '{ "l3_device": "br-lan" }'
|
||||||
|
}
|
||||||
|
ip() {
|
||||||
|
case "$*" in
|
||||||
|
'-6 route show dev br-lan')
|
||||||
|
echo 'default from 240e:1234:5600::/56 via fe80::1 dev br-lan'
|
||||||
|
echo '240e:1234:5600:1::/64 dev br-lan proto static'
|
||||||
|
;;
|
||||||
|
'-6 route show default') echo 'default from 240e:1234:5600::/56 via fe80::1 dev pppoe-wan' ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
actual=$(get_ipv6_prefixes)
|
||||||
|
assert_equal '240e:1234:5600:1::/64' "$actual"
|
||||||
|
|
||||||
|
# OpenWrt falls back to source-specific routes when its LAN route is hidden.
|
||||||
|
lan_ifaces=
|
||||||
|
ubus() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
ip() {
|
||||||
|
case "$*" in
|
||||||
|
'-6 route show default') echo 'default from 240e:1234:5600::/56 via fe80::1 dev pppoe-wan' ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
actual=$(get_ipv6_prefixes)
|
||||||
|
assert_equal '240e:1234:5600::/56' "$actual"
|
||||||
|
|
||||||
|
# Standard Linux uses the directly connected route on the discovered LAN.
|
||||||
|
systype=container
|
||||||
|
lan_ifaces='enp2s0'
|
||||||
|
ip() {
|
||||||
|
case "$*" in
|
||||||
|
'-6 route show dev enp2s0') echo '2408:8266:501:2443::/64 dev enp2s0 proto kernel metric 256' ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
actual=$(get_ipv6_prefixes)
|
||||||
|
assert_equal '2408:8266:501:2443::/64' "$actual"
|
||||||
|
|
||||||
|
# BusyBox based router firmware does not need route protocol metadata.
|
||||||
|
systype=Padavan
|
||||||
|
lan_ifaces='br0'
|
||||||
|
ip() {
|
||||||
|
case "$*" in
|
||||||
|
'-6 route show dev br0') echo '2001:db8:abcd:1::/64 dev br0 metric 256' ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
actual=$(get_ipv6_prefixes)
|
||||||
|
assert_equal '2001:db8:abcd:1::/64' "$actual"
|
||||||
|
|
||||||
|
ts_service=ON
|
||||||
|
wg_service=OFF
|
||||||
|
build_host_ipv6 '2408:8266:501:2443::/64 invalid-value'
|
||||||
|
assert_equal '2408:8266:501:2443::/64 fd00::/8 fd7a:115c:a1e0::/48 fe80::/10' "$host_ipv6"
|
||||||
|
|
||||||
|
echo 'IPv6 prefix tests passed'
|
||||||
Executable
+78
@@ -0,0 +1,78 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
ROOT=$(cd "$(dirname "$0")/.." && pwd)
|
||||||
|
|
||||||
|
reserve_ipv4='0.0.0.0/8 127.0.0.0/8'
|
||||||
|
reserve_ipv6='::/128 ::1/128 fe80::/10 ff00::/8'
|
||||||
|
host_ipv4='192.168.1.0/24'
|
||||||
|
local_ipv4='192.168.1.1'
|
||||||
|
host_ipv6='2001:db8:1::/64 fd00::/8 fe80::/10'
|
||||||
|
common_ports=OFF
|
||||||
|
ports=
|
||||||
|
PORTS=
|
||||||
|
mix_port=7890
|
||||||
|
redir_port=7892
|
||||||
|
tproxy_port=7893
|
||||||
|
dns_redir_port=1053
|
||||||
|
routing_mark=7894
|
||||||
|
fwmark=7892
|
||||||
|
firewall_area=3
|
||||||
|
macfilter_type='黑名单'
|
||||||
|
cn_ip_route=OFF
|
||||||
|
dns_mod=route
|
||||||
|
ipv6_redir=ON
|
||||||
|
quic_rj=OFF
|
||||||
|
lan_proxy=true
|
||||||
|
local_proxy=true
|
||||||
|
redir_mod=Tproxy
|
||||||
|
tun_statu=false
|
||||||
|
vm_redir=OFF
|
||||||
|
fw_wan=ON
|
||||||
|
fw_wan_ports=
|
||||||
|
vms_port=
|
||||||
|
sss_port=
|
||||||
|
db_port=9090
|
||||||
|
systype=linux
|
||||||
|
CRASHDIR=/nonexistent
|
||||||
|
BINDIR=/nonexistent
|
||||||
|
|
||||||
|
nft() {
|
||||||
|
if [ "$1" = list ] && [ "$2" = set ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
printf '%s' "$1"
|
||||||
|
shift
|
||||||
|
printf ' %s' "$@"
|
||||||
|
printf '\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
modprobe() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
. "$ROOT/scripts/starts/fw_nftables.sh"
|
||||||
|
rules=$(start_nftables || :)
|
||||||
|
|
||||||
|
require_rule() {
|
||||||
|
if ! printf '%s\n' "$rules" | grep -Fq "$1"; then
|
||||||
|
echo "missing generated rule: $1" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
require_rule 'add set inet shellcrash lan_ip6'
|
||||||
|
require_rule 'flags interval ; auto-merge'
|
||||||
|
require_rule 'add element inet shellcrash lan_ip6'
|
||||||
|
require_rule 'add rule inet shellcrash prerouting ip6 daddr @lan_ip6 return'
|
||||||
|
require_rule 'add rule inet shellcrash prerouting ip6 saddr != @lan_ip6 return'
|
||||||
|
require_rule 'add rule inet shellcrash prerouting_dns ip6 saddr != @lan_ip6 return'
|
||||||
|
require_rule 'add rule inet shellcrash input ip6 saddr @lan_ip6 accept'
|
||||||
|
require_rule 'add rule inet shellcrash output ip6 daddr @lan_ip6 return'
|
||||||
|
|
||||||
|
if printf '%s\n' "$rules" | grep -Fq 'add rule inet shellcrash output ip6 saddr'; then
|
||||||
|
echo 'output must not depend on a dynamic IPv6 source prefix' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo 'nftables IPv6 rule generation tests passed'
|
||||||
Reference in New Issue
Block a user