Merge pull request #252 from yangtaowillv/feature/add-LAN

feat: add ALLOW-LAN; command: clashctl lan status/on/off
This commit is contained in:
Arvin
2026-05-07 12:51:19 +08:00
committed by GitHub
12 changed files with 245 additions and 95 deletions
+9 -9
View File
@@ -1,9 +1,9 @@
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
[*.{sh,yaml,yml,env,md}]
charset = utf-8
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
[*.{sh,yaml,yml,env,md}]
charset = utf-8
+2 -2
View File
@@ -2,10 +2,10 @@
export KERNEL_TYPE="mihomo"
# 可选订阅(首次安装可留空)
export CLASH_SUBSCRIPTION_URL=""
export CLASH_SUBSCRIPTION_URL="https://sakuracat1203.xn--3iq226gfdb94q.com/api/v1/client/subscribe?token=df9fd8af2086471190a42435d354a3ec"
# 控制器密钥(默认留空)
export CLASH_CONTROLLER_SECRET=""
export CLASH_CONTROLLER_SECRET="f4962effeac0815d"
# 端口
export MIXED_PORT="7890"
+7 -7
View File
@@ -1,7 +1,7 @@
*.sh text eol=lf working-tree-encoding=UTF-8
*.yaml text eol=lf
*.yml text eol=lf
*.env text eol=lf
*.gz binary
*.zip binary
*.mmdb binary
*.sh text eol=lf working-tree-encoding=UTF-8
*.yaml text eol=lf
*.yml text eol=lf
*.env text eol=lf
*.gz binary
*.zip binary
*.mmdb binary
+18 -18
View File
@@ -1,18 +1,18 @@
# IDE
.idea/
.vscode/
# Local env
.env
# Runtime
runtime/
# Local dashboard unpacked files
resources/dashboard/dist/
# Keep packaged dashboard asset
!resources/dashboard/dist.zip
# Local test scripts
test.sh
# IDE
.idea/
.vscode/
# Local env
.env
# Runtime
runtime/
# Local dashboard unpacked files
resources/dashboard/dist/
# Keep packaged dashboard asset
!resources/dashboard/dist.zip
# Local test scripts
test.sh
+19 -19
View File
@@ -1,19 +1,19 @@
Copyright (c) 2026 wnlen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Copyright (c) 2026 wnlen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+15
View File
@@ -70,6 +70,7 @@ bash install.sh
clashctl secret 🔑 查看密钥
clashctl secret 123 🔐 设置密钥
📌 高级
clashctl lan 🏠 局域网代理管理
clashctl tun 🧪 Tun 模式管理
clashctl boot 🚦 开机代理接管管理
clashctl mixin 🧩 Mixin 配置管理
@@ -117,6 +118,20 @@ $ clashsecret
------
## 🏠 局域网代理
项目默认开启局域网代理:运行配置会写入 `allow-lan: true`,并把 `external-controller` 绑定到 `0.0.0.0`,避免订阅文件里的 `allow-lan: false` 覆盖项目默认值。
```bash
clashctl lan status
clashctl lan on
clashctl lan off
```
开启后,同一局域网设备可把 HTTP / SOCKS 代理地址设置为 `http://<本机局域网IP>:<mixed-port>`,端口默认是 `7890`;如访问不了,请检查系统防火墙是否放行该端口。
------
OpenWrt 下 root/system 安装会把 `clashctl`、`clashon`、`clashoff` 等命令入口写入 `/usr/bin`,运行状态、日志和内核二进制仍保存在项目目录的 `runtime/` 下。仅脚本模式不会注册开机自启,设备重启后需要重新执行 `clashon`。
## 🧰 常用管理命令
+1 -1
View File
@@ -2,7 +2,7 @@ mixed-port: 7890
allow-lan: true
mode: rule
log-level: info
external-controller: 127.0.0.1:9090
external-controller: 0.0.0.0:9090
tun:
enable: false
stack: system
+36 -36
View File
@@ -1,36 +1,36 @@
# 内置运行依赖
如果安装时 GitHub 下载太慢,可以把 Mihomo、yq、subconverter 提前放到本目录。安装和 `clashctl upgrade` 会优先读取这里的文件;没有匹配文件时,仍会回退到原来的下载逻辑。
Clash 是兼容内核,固定走远程下载,不使用本目录中的本地资源。
默认目录结构:
```text
resources/bin/
mihomo/
mihomo-linux-amd64-compatible-v1.19.23.gz
mihomo-linux-arm64-v1.19.23.gz
mihomo-linux-armv7-v1.19.23.gz
yq/
yq_linux_amd64.tar.gz
yq_linux_arm64.tar.gz
yq_linux_arm.tar.gz
subconverter/
subconverter_linux64.tar.gz
subconverter_aarch64.tar.gz
subconverter_armv7.tar.gz
```
当前正式支持 `amd64`、`arm64`、`armv7`。版本号要和 `.env` 里的 `MIHOMO_VERSION`、`YQ_VERSION`、`SUBCONVERTER_VERSION` 对应。脚本只按当前目标文件名精确命中,不会扫描目录,也不会自动选择最高版本;如果本地没有对应文件,会继续联网下载。
Mihomo、yq、subconverter 兼容旧路径 `resources/bin/<category>/<version>/<file>`,但默认推荐直接使用 `resources/bin/<category>/<file>`。
可选开关:
```bash
export CLASH_BUNDLED_ASSET_ENABLED=false
export CLASH_BUNDLED_ASSET_DIR=/path/to/assets
```
`Country.mmdb` 仍放在 `resources/geo/Country.mmdb` 或 `resources/geo/country.mmdb`。
# 内置运行依赖
如果安装时 GitHub 下载太慢,可以把 Mihomo、yq、subconverter 提前放到本目录。安装和 `clashctl upgrade` 会优先读取这里的文件;没有匹配文件时,仍会回退到原来的下载逻辑。
Clash 是兼容内核,固定走远程下载,不使用本目录中的本地资源。
默认目录结构:
```text
resources/bin/
mihomo/
mihomo-linux-amd64-compatible-v1.19.23.gz
mihomo-linux-arm64-v1.19.23.gz
mihomo-linux-armv7-v1.19.23.gz
yq/
yq_linux_amd64.tar.gz
yq_linux_arm64.tar.gz
yq_linux_arm.tar.gz
subconverter/
subconverter_linux64.tar.gz
subconverter_aarch64.tar.gz
subconverter_armv7.tar.gz
```
当前正式支持 `amd64`、`arm64`、`armv7`。版本号要和 `.env` 里的 `MIHOMO_VERSION`、`YQ_VERSION`、`SUBCONVERTER_VERSION` 对应。脚本只按当前目标文件名精确命中,不会扫描目录,也不会自动选择最高版本;如果本地没有对应文件,会继续联网下载。
Mihomo、yq、subconverter 兼容旧路径 `resources/bin/<category>/<version>/<file>`,但默认推荐直接使用 `resources/bin/<category>/<file>`。
可选开关:
```bash
export CLASH_BUNDLED_ASSET_ENABLED=false
export CLASH_BUNDLED_ASSET_DIR=/path/to/assets
```
`Country.mmdb` 仍放在 `resources/geo/Country.mmdb` 或 `resources/geo/country.mmdb`。
+81
View File
@@ -34,6 +34,7 @@ Usage:
config kernel mihomo|clash 🧩 切换指定内核
mixin 🧩 Mixin 配置管理
relay 🔗 多跳节点管理
lan 🏠 局域网代理管理
📦 Subscription:
@@ -45,6 +46,7 @@ Usage:
🕹️ Control:
clashui 🕹️ 查看 Web 控制台
secret 🔑 查看或设置 Web 密钥
lan on|off|status 🏠 开启 / 关闭局域网代理
🧪 Transparent proxy:
tun 🧪 Tun 模式管理
@@ -2301,6 +2303,7 @@ status_port_adjustment_brief() {
print_status_summary_compact() {
local profile mixed_port controller controller_lan controller_public
local allow_lan lan_proxy
local running_text user_connectivity user_risk current_proxy_brief system_proxy_text
local current_active dashboard_text dashboard_source_text dashboard_policy_text secret_text
local tun_text bind_failure_text next_action
@@ -2309,6 +2312,7 @@ print_status_summary_compact() {
[ -n "${profile:-}" ] || profile="default"
mixed_port="$(status_read_mixed_port 2>/dev/null || true)"
allow_lan="$(runtime_config_allow_lan 2>/dev/null || config_allow_lan 2>/dev/null || echo true)"
controller="$(status_read_controller 2>/dev/null || true)"
controller_lan="$(status_read_controller_lan 2>/dev/null || true)"
controller_public="$(status_read_controller_public 2>/dev/null || true)"
@@ -2386,6 +2390,12 @@ print_status_summary_compact() {
if [ -n "${mixed_port:-}" ] && [ "$mixed_port" != "null" ]; then
echo "🌐 本地代理:http://127.0.0.1:${mixed_port}"
if [ "$allow_lan" = "true" ]; then
lan_proxy="$(ui_lan_ip 2>/dev/null || true)"
[ -n "${lan_proxy:-}" ] && echo "🏠 局域网代理:http://${lan_proxy}:${mixed_port}"
else
echo "🏠 局域网代理:已关闭"
fi
else
echo "🌐 本地代理:未知"
fi
@@ -2410,6 +2420,7 @@ print_status_summary_compact() {
print_status_summary_verbose() {
local running_text profile mixed_port controller controller_lan controller_public
local allow_lan lan_proxy
local current_active build_active_sources build_failed_active_sources build_status build_time
local build_block_reason build_block_time
local last_switch_from last_switch_to last_switch_time
@@ -2426,6 +2437,7 @@ print_status_summary_verbose() {
[ -n "${profile:-}" ] || profile="default"
mixed_port="$(status_read_mixed_port 2>/dev/null || true)"
allow_lan="$(runtime_config_allow_lan 2>/dev/null || config_allow_lan 2>/dev/null || echo true)"
controller="$(status_read_controller 2>/dev/null || true)"
controller_lan="$(status_read_controller_lan 2>/dev/null || true)"
controller_public="$(status_read_controller_public 2>/dev/null || true)"
@@ -2532,6 +2544,12 @@ print_status_summary_verbose() {
echo "🔧 Profile:$profile"
if [ -n "${mixed_port:-}" ] && [ "$mixed_port" != "null" ]; then
echo "🌐 本地代理:http://127.0.0.1:${mixed_port}"
if [ "$allow_lan" = "true" ]; then
lan_proxy="$(ui_lan_ip 2>/dev/null || true)"
[ -n "${lan_proxy:-}" ] && echo "🏠 局域网代理:http://${lan_proxy}:${mixed_port}"
else
echo "🏠 局域网代理:已关闭"
fi
else
echo "🌐 本地代理:未知"
fi
@@ -2960,6 +2978,7 @@ cmd_ui_help_summary() {
printf ' %-18s %s\n' "clashctl use" "💱 切换订阅"
printf ' %-18s %s\n' "clashctl ls" "📜 查看订阅列表"
echo "📌 高级"
printf ' %-18s %s\n' "clashctl lan" "🏠 局域网代理管理"
printf ' %-18s %s\n' "clashctl tun" "🧪 Tun 模式管理"
printf ' %-18s %s\n' "clashctl mixin" "🧩 Mixin 配置管理"
printf ' %-18s %s\n' "clashctl sub" "🧩 订阅高级管理(启用 / 禁用 / 重命名 / 删除)"
@@ -3890,6 +3909,67 @@ cmd_config() {
esac
}
print_lan_status() {
local allow_lan mixed_port lan_ip
allow_lan="$(runtime_config_allow_lan 2>/dev/null || config_allow_lan 2>/dev/null || echo true)"
mixed_port="$(status_read_mixed_port 2>/dev/null || runtime_config_mixed_port 2>/dev/null || true)"
lan_ip="$(ui_lan_ip 2>/dev/null || true)"
ui_title "🏠 局域网代理"
if [ "$allow_lan" = "true" ]; then
ui_kv "📶" "状态" "已开启"
if [ -n "${lan_ip:-}" ] && [ -n "${mixed_port:-}" ] && [ "$mixed_port" != "null" ]; then
ui_kv "🏠" "局域网代理" "http://${lan_ip}:${mixed_port}"
else
ui_kv "🏠" "局域网代理" "等待运行配置生成"
fi
else
ui_kv "📶" "状态" "已关闭"
fi
ui_kv "🔧" "配置项" "allow-lan: ${allow_lan}"
ui_blank
}
cmd_lan() {
local action
prepare
action="${1:-status}"
case "$action" in
on|enable)
set_config_allow_lan true
regenerate_config
apply_runtime_change_after_config_mutation
success "局域网代理已开启"
print_lan_status
print_config_apply_feedback
;;
off|disable)
set_config_allow_lan false
regenerate_config
apply_runtime_change_after_config_mutation
success "局域网代理已关闭"
print_lan_status
print_config_apply_feedback
;;
status)
print_lan_status
ui_next "clashctl lan on"
ui_blank
;;
-h|--help|help|"")
echo "📜 用法:"
echo " clashctl lan status"
echo " clashctl lan on"
echo " clashctl lan off"
;;
*)
die_usage "未知的 lan 子命令:$action" "clashctl lan on|off|status"
;;
esac
}
print_profile_use_feedback() {
local profile="$1"
@@ -7303,6 +7383,7 @@ case "$cmd" in
tun) cmd_tun "$@" ;;
dev) cmd_dev "$@" ;;
config) cmd_config "$@" ;;
lan) cmd_lan "$@" ;;
mixin) cmd_mixin "$@" ;;
relay) cmd_relay "$@" ;;
profile) cmd_profile "$@" ;;
+13
View File
@@ -1754,6 +1754,19 @@ runtime_config_controller_port() {
echo "$port"
}
runtime_config_allow_lan() {
local file
local value
file="$(runtime_config_file)"
[ -s "$file" ] || return 1
value="$("$(yq_bin)" eval '.["allow-lan"] // true' "$file" 2>/dev/null | head -n 1)"
case "$value" in
false) echo "false" ;;
*) echo "true" ;;
esac
}
runtime_port_value_is_valid() {
local port="${1:-}"
+13 -1
View File
@@ -170,6 +170,17 @@ _clash_for_linux_complete_config() {
fi
}
_clash_for_linux_complete_lan() {
local cur="$1"
local rel_index="$2"
COMPREPLY=()
if [ "$rel_index" -eq 1 ]; then
_clash_for_linux_add_matches "$cur" on off status enable disable help -h --help
fi
}
_clash_for_linux_complete_mixin() {
local cur="$1"
local rel_index="$2"
@@ -304,7 +315,7 @@ _clash_for_linux_complete_top_level() {
COMPREPLY=()
_clash_for_linux_add_matches "$cur" \
add use ls health select on off status status-next \
boot log logs doctor ui secret tun dev config mixin \
boot log logs doctor ui secret tun dev config lan mixin \
relay profile sub proxy upgrade update completion help \
-h --help
}
@@ -368,6 +379,7 @@ _clash_for_linux_complete_command() {
status) _clash_for_linux_complete_status "$cur" ;;
boot) _clash_for_linux_complete_boot "$cur" "$rel_index" "$arg1" ;;
config) _clash_for_linux_complete_config "$cur" "$rel_index" "$arg1" ;;
lan) _clash_for_linux_complete_lan "$cur" "$rel_index" ;;
mixin) _clash_for_linux_complete_mixin "$cur" "$rel_index" ;;
relay) _clash_for_linux_complete_relay "$cur" "$rel_index" "$arg1" ;;
sub) _clash_for_linux_complete_sub "$cur" "$rel_index" "$arg1" ;;
+31 -2
View File
@@ -379,6 +379,33 @@ render_base_config() {
fi
}
config_allow_lan() {
local file="$CONFIG_DIR/template.yaml"
local value
ensure_config_files
value="$("$(yq_bin)" eval '.["allow-lan"] // true' "$file" 2>/dev/null | head -n 1)"
case "$value" in
false) echo "false" ;;
*) echo "true" ;;
esac
}
set_config_allow_lan() {
local value="$1"
local file="$CONFIG_DIR/template.yaml"
case "$value" in
true|false) ;;
*) die "allow-lan 只允许 true 或 false" ;;
esac
ensure_config_files
ALLOW_LAN_VALUE="$value" "$(yq_bin)" eval -i '
.["allow-lan"] = (env(ALLOW_LAN_VALUE) == "true")
' "$file"
}
subscription_url_scheme() {
local url="$1"
@@ -766,7 +793,7 @@ normalize_runtime_config() {
local file="$1"
local mixed_port controller tun_enable_value tun_stack_value dns_port_value controller_secret_value
local tun_auto_route_value tun_auto_redirect_value tun_strict_route_value tun_dns_hijack_value
local dashboard_dir_value
local dashboard_dir_value allow_lan_value
local resolved_ports err_file output
[ -s "$file" ] || die "待规范化的配置文件不存在:$file"
@@ -785,10 +812,12 @@ normalize_runtime_config() {
dns_port_value="$CLASH_DNS_PORT_RESOLVED"
controller_secret_value="$(ensure_controller_secret)"
dashboard_dir_value="$(runtime_dashboard_dir)"
allow_lan_value="$(config_allow_lan 2>/dev/null || echo true)"
err_file="$(mktemp)"
if ! mixed_port="$mixed_port" \
controller="$controller" \
allow_lan_value="$allow_lan_value" \
tun_enable_value="$tun_enable_value" \
tun_stack_value="$tun_stack_value" \
tun_auto_route_value="$tun_auto_route_value" \
@@ -804,7 +833,7 @@ normalize_runtime_config() {
.secret = env(controller_secret_value) |
.["external-ui"] = env(dashboard_dir_value) |
.["external-ui-url"] = "/ui" |
.["allow-lan"] = (.["allow-lan"] // true) |
.["allow-lan"] = (env(allow_lan_value) == "true") |
.mode = "rule" |
.["log-level"] = (.["log-level"] // "info") |