From e070d7b6939792da36ce8f174bebae88c0525e9f Mon Sep 17 00:00:00 2001 From: wnlen <62139570+wnlen@users.noreply.github.com> Date: Wed, 14 Jan 2026 21:57:55 +0800 Subject: [PATCH 01/20] Update fallback_config.yaml --- conf/fallback_config.yaml | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/conf/fallback_config.yaml b/conf/fallback_config.yaml index 444a1d1..7ef7995 100644 --- a/conf/fallback_config.yaml +++ b/conf/fallback_config.yaml @@ -1,9 +1,24 @@ mixed-port: 7890 allow-lan: false +bind-address: '*' mode: rule log-level: info - +ipv6: true +external-controller: 127.0.0.1:9090 +secret: "${CLASH_SECRET}" +external-ui: /opt/clash-for-linux/ui +dns: + enable: true + listen: 127.0.0.1:1053 + enhanced-mode: fake-ip + nameserver: + - 223.5.5.5 + - 119.29.29.29 proxies: [] - +proxy-groups: + - name: "DIRECT" + type: select + proxies: + - DIRECT rules: - MATCH,DIRECT From 8f0f74cff3febb54d3a8b5cbebc35a3acbd5523d Mon Sep 17 00:00:00 2001 From: wnlen <62139570+wnlen@users.noreply.github.com> Date: Wed, 14 Jan 2026 21:58:10 +0800 Subject: [PATCH 02/20] Update config.yaml --- conf/config.yaml | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/conf/config.yaml b/conf/config.yaml index f1b4f85..1224bb3 100644 --- a/conf/config.yaml +++ b/conf/config.yaml @@ -1,9 +1,24 @@ mixed-port: 7890 allow-lan: false +bind-address: '*' mode: rule log-level: info - +ipv6: true +external-controller: 127.0.0.1:9090 +secret: "${CLASH_SECRET}" +external-ui: /opt/clash-for-linux/ui +dns: + enable: true + listen: 127.0.0.1:1053 + enhanced-mode: fake-ip + nameserver: + - 223.5.5.5 + - 119.29.29.29 proxies: [] - +proxy-groups: + - name: "DIRECT" + type: select + proxies: + - DIRECT rules: - MATCH,DIRECT From fb950854f1cd8d1b9023e60503906d1deab77097 Mon Sep 17 00:00:00 2001 From: wnlen <62139570+wnlen@users.noreply.github.com> Date: Wed, 14 Jan 2026 22:09:16 +0800 Subject: [PATCH 03/20] Update config.yaml --- conf/config.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/conf/config.yaml b/conf/config.yaml index 1224bb3..89e6b74 100644 --- a/conf/config.yaml +++ b/conf/config.yaml @@ -5,7 +5,7 @@ mode: rule log-level: info ipv6: true external-controller: 127.0.0.1:9090 -secret: "${CLASH_SECRET}" +secret: 'SECRET_PLACEHOLDER' external-ui: /opt/clash-for-linux/ui dns: enable: true @@ -22,3 +22,4 @@ proxy-groups: - DIRECT rules: - MATCH,DIRECT + From c9d8fb06d6cc14295093b8f977a40c4f58396a8a Mon Sep 17 00:00:00 2001 From: wnlen <62139570+wnlen@users.noreply.github.com> Date: Wed, 14 Jan 2026 22:09:28 +0800 Subject: [PATCH 04/20] Update fallback_config.yaml --- conf/fallback_config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/fallback_config.yaml b/conf/fallback_config.yaml index 7ef7995..e629027 100644 --- a/conf/fallback_config.yaml +++ b/conf/fallback_config.yaml @@ -5,7 +5,7 @@ mode: rule log-level: info ipv6: true external-controller: 127.0.0.1:9090 -secret: "${CLASH_SECRET}" +secret: 'SECRET_PLACEHOLDER' external-ui: /opt/clash-for-linux/ui dns: enable: true From 3fd6d3326a8516931fe61b5a532e3af85d58b857 Mon Sep 17 00:00:00 2001 From: wnlen <62139570+wnlen@users.noreply.github.com> Date: Wed, 14 Jan 2026 22:18:04 +0800 Subject: [PATCH 05/20] Update start.sh --- start.sh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/start.sh b/start.sh index db2d94d..2f76acf 100644 --- a/start.sh +++ b/start.sh @@ -53,15 +53,25 @@ else fi fi -# 获取 CLASH_SECRET 值:优先 .env;否则尝试读取旧 config;否则生成随机数 +# 获取 CLASH_SECRET 值:优先 .env;其次读取旧 config;占位符视为无效;最后生成随机值 Secret="${CLASH_SECRET:-}" + +# 尝试从旧 config.yaml 读取(仅当 .env 未提供) if [ -z "$Secret" ] && [ -f "$Conf_Dir/config.yaml" ]; then - Secret="$(awk -F': ' '/^secret:/{print $2; exit}' "$Conf_Dir/config.yaml" || true)" + Secret="$(awk -F': *' '/^secret:/{gsub(/"/,"",$2); print $2; exit}' "$Conf_Dir/config.yaml" || true)" fi + +# 若读取到的是占位符(如 ${CLASH_SECRET}),视为无效 +if [[ "$Secret" =~ ^\$\{.*\}$ ]]; then + Secret="" +fi + +# 兜底生成随机 secret if [ -z "$Secret" ]; then Secret="$(openssl rand -hex 32)" fi + # 设置默认值 CLASH_HTTP_PORT="${CLASH_HTTP_PORT:-7890}" CLASH_SOCKS_PORT="${CLASH_SOCKS_PORT:-7891}" From 5dd8c68f08c412194ed1db0287cfd0c0c5a66505 Mon Sep 17 00:00:00 2001 From: wnlen <62139570+wnlen@users.noreply.github.com> Date: Wed, 14 Jan 2026 22:21:01 +0800 Subject: [PATCH 06/20] Update start.sh --- start.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/start.sh b/start.sh index 2f76acf..fc75d86 100644 --- a/start.sh +++ b/start.sh @@ -347,6 +347,12 @@ if [ ! -s "$Conf_Dir/config.yaml" ]; then exit 1 fi +# 最终护栏:禁止未渲染的占位符进入运行态 +if grep -q '\${' "$Conf_Dir/config.yaml"; then + echo "[ERROR] config.yaml contains unresolved placeholders (\${...}). Please check template rendering." >&2 + exit 1 +fi + echo -e '\n正在启动Clash服务...' Text5="服务启动成功!" Text6="服务启动失败!" From 0c4b099f3baf81e5916a28d7df5b435fbbe2c1d5 Mon Sep 17 00:00:00 2001 From: wnlen <62139570+wnlen@users.noreply.github.com> Date: Wed, 14 Jan 2026 22:41:10 +0800 Subject: [PATCH 07/20] Update fallback_config.yaml --- conf/fallback_config.yaml | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/conf/fallback_config.yaml b/conf/fallback_config.yaml index e629027..e4e5873 100644 --- a/conf/fallback_config.yaml +++ b/conf/fallback_config.yaml @@ -4,21 +4,13 @@ bind-address: '*' mode: rule log-level: info ipv6: true +udp: true + external-controller: 127.0.0.1:9090 -secret: 'SECRET_PLACEHOLDER' -external-ui: /opt/clash-for-linux/ui -dns: - enable: true - listen: 127.0.0.1:1053 - enhanced-mode: fake-ip - nameserver: - - 223.5.5.5 - - 119.29.29.29 +secret: "SECRET_PLACEHOLDER" + proxies: [] -proxy-groups: - - name: "DIRECT" - type: select - proxies: - - DIRECT +proxy-groups: [] + rules: - MATCH,DIRECT From 1911a0fc100b4e2586f34133c9b1d39418391399 Mon Sep 17 00:00:00 2001 From: wnlen <62139570+wnlen@users.noreply.github.com> Date: Wed, 14 Jan 2026 22:41:20 +0800 Subject: [PATCH 08/20] Update config.yaml --- conf/config.yaml | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/conf/config.yaml b/conf/config.yaml index 89e6b74..b86e767 100644 --- a/conf/config.yaml +++ b/conf/config.yaml @@ -4,22 +4,13 @@ bind-address: '*' mode: rule log-level: info ipv6: true +udp: true + external-controller: 127.0.0.1:9090 -secret: 'SECRET_PLACEHOLDER' -external-ui: /opt/clash-for-linux/ui -dns: - enable: true - listen: 127.0.0.1:1053 - enhanced-mode: fake-ip - nameserver: - - 223.5.5.5 - - 119.29.29.29 +secret: "SECRET_PLACEHOLDER" + proxies: [] -proxy-groups: - - name: "DIRECT" - type: select - proxies: - - DIRECT +proxy-groups: [] + rules: - MATCH,DIRECT - From c2d53e4a4a6fadb229bb616941c69e988f3e07ba Mon Sep 17 00:00:00 2001 From: wnlen <62139570+wnlen@users.noreply.github.com> Date: Wed, 14 Jan 2026 23:01:51 +0800 Subject: [PATCH 09/20] Update start.sh --- start.sh | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/start.sh b/start.sh index fc75d86..bda71ff 100644 --- a/start.sh +++ b/start.sh @@ -71,6 +71,19 @@ if [ -z "$Secret" ]; then Secret="$(openssl rand -hex 32)" fi +# 强制写入 secret 到指定配置文件(存在则替换,不存在则追加) +force_write_secret() { + local file="$1" + [ -f "$file" ] || return 0 + + if grep -qE '^[[:space:]]*secret:' "$file"; then + # 替换整行 secret(无论原来是啥,包括 SECRET_PLACEHOLDER / "${CLASH_SECRET}") + sed -i -E "s|^[[:space:]]*secret:.*$|secret: ${Secret}|g" "$file" + else + # 没有 secret 行就追加到文件末尾 + printf "\nsecret: %s\n" "$Secret" >> "$file" + fi +} # 设置默认值 CLASH_HTTP_PORT="${CLASH_HTTP_PORT:-7890}" @@ -165,6 +178,8 @@ ensure_fallback_config() { exit 1 fi fi + # 强制写入真实 secret + force_write_secret "$Conf_Dir/config.yaml" } SKIP_CONFIG_REBUILD=false @@ -329,11 +344,11 @@ if [ "$SKIP_CONFIG_REBUILD" != "true" ]; then fi # 写入 secret - sed -r -i "/^secret: /s@(secret: ).*@\1${Secret}@g" "$Conf_Dir/config.yaml" || true + force_write_secret "$Conf_Dir/config.yaml" else # 兜底路径:尽量也写入 secret(若 config 里有 secret: 行就替换;没有就追加) if grep -qE '^secret:\s*' "$Conf_Dir/config.yaml" 2>/dev/null; then - sed -r -i "/^secret: /s@(secret: ).*@\1${Secret}@g" "$Conf_Dir/config.yaml" || true + force_write_secret "$Conf_Dir/config.yaml" else echo "secret: ${Secret}" >> "$Conf_Dir/config.yaml" || true fi From 017ecebcecaca1ea411fd6c6e77d062833fd6f36 Mon Sep 17 00:00:00 2001 From: wnlen <62139570+wnlen@users.noreply.github.com> Date: Wed, 14 Jan 2026 23:02:30 +0800 Subject: [PATCH 10/20] Update fallback_config.yaml --- conf/fallback_config.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/conf/fallback_config.yaml b/conf/fallback_config.yaml index e4e5873..378f798 100644 --- a/conf/fallback_config.yaml +++ b/conf/fallback_config.yaml @@ -7,7 +7,6 @@ ipv6: true udp: true external-controller: 127.0.0.1:9090 -secret: "SECRET_PLACEHOLDER" proxies: [] proxy-groups: [] From 053504df69a0fa7858af6772c216d67ea07e81f0 Mon Sep 17 00:00:00 2001 From: wnlen <62139570+wnlen@users.noreply.github.com> Date: Wed, 14 Jan 2026 23:02:39 +0800 Subject: [PATCH 11/20] Update config.yaml --- conf/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/config.yaml b/conf/config.yaml index b86e767..9a88d18 100644 --- a/conf/config.yaml +++ b/conf/config.yaml @@ -7,10 +7,10 @@ ipv6: true udp: true external-controller: 127.0.0.1:9090 -secret: "SECRET_PLACEHOLDER" proxies: [] proxy-groups: [] rules: - MATCH,DIRECT + From e1b48719741ce5afdd25395453fc32d886811a21 Mon Sep 17 00:00:00 2001 From: wnlen <62139570+wnlen@users.noreply.github.com> Date: Wed, 14 Jan 2026 23:08:30 +0800 Subject: [PATCH 12/20] Update start.sh --- start.sh | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/start.sh b/start.sh index bda71ff..3b5ba9a 100644 --- a/start.sh +++ b/start.sh @@ -391,7 +391,19 @@ if_success "$Text5" "$Text6" "$ReturnStatus" echo '' if [ "$EXTERNAL_CONTROLLER_ENABLED" = "true" ]; then echo -e "Clash Dashboard 访问地址: http://${EXTERNAL_CONTROLLER}/ui" - echo -e "Secret: ${Secret}" + + SHOW_SECRET="${CLASH_SHOW_SECRET:-false}" + SHOW_SECRET_MASKED="${CLASH_SHOW_SECRET_MASKED:-true}" + + if [ "$SHOW_SECRET" = "true" ]; then + echo -e "Secret: ${Secret}" + elif [ "$SHOW_SECRET_MASKED" = "true" ]; then + # 脱敏:前4后4 + masked="${Secret:0:4}****${Secret: -4}" + echo -e "Secret: ${masked} (set CLASH_SHOW_SECRET=true to show full)" + else + echo -e "Secret: 已生成(未显示)。查看:/opt/clash-for-linux/conf/config.yaml 或 .env" + fi else echo -e "External Controller (Dashboard) 已禁用" fi From b01724d37c4d47439db43bc7c45fefbdd3153c3e Mon Sep 17 00:00:00 2001 From: wnlen <62139570+wnlen@users.noreply.github.com> Date: Wed, 14 Jan 2026 23:15:49 +0800 Subject: [PATCH 13/20] Add options for showing Clash API secrets Add configuration options for displaying secrets in output --- .env | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.env b/.env index dcc7801..c120385 100644 --- a/.env +++ b/.env @@ -31,6 +31,12 @@ export CLASH_SUBSCRIPTION='' # 留空时:脚本可自动生成随机值(若你的启动脚本支持) export CLASH_SECRET='' +# 是否在启动输出中显示完整 Secret(不推荐) +CLASH_SHOW_SECRET=false + +# 是否显示脱敏 Secret(推荐) +CLASH_SHOW_SECRET_MASKED=true + # External Controller(Clash RESTful API) # ⚠️ 安全建议: # - 默认仅监听本机:127.0.0.1:9090 (推荐) From 5de2a5b9c9bab104ecaad503d84253cbbcb6a47b Mon Sep 17 00:00:00 2001 From: wnlen <62139570+wnlen@users.noreply.github.com> Date: Wed, 14 Jan 2026 23:25:46 +0800 Subject: [PATCH 14/20] Update install.sh --- install.sh | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/install.sh b/install.sh index fd9a98e..69eb725 100755 --- a/install.sh +++ b/install.sh @@ -241,11 +241,28 @@ if [ -z "$api_host" ] || [ "$api_host" = "$EXTERNAL_CONTROLLER" ]; then fi echo -e "🌐 Dashboard:http://${api_host}:${api_port}/ui" -# secret 可能在 .env 里是 CLASH_SECRET -if [ -n "${CLASH_SECRET:-}" ]; then - echo -e "🔐 Secret:${CLASH_SECRET}" +# ---- Secret 展示(脱敏)---- +CONF_DIR="${CLASH_INSTALL_DIR:-/opt/clash-for-linux}/conf" +CONF_FILE="$CONF_DIR/config.yaml" + +# 读取 secret(如果 clash 还没生成 config,就先不显示) +SECRET_VAL="" +if [ -f "$CONF_FILE" ]; then + SECRET_VAL="$(awk -F': *' '/^secret:/{print $2; exit}' "$CONF_FILE" | tr -d '"' | tr -d "'" )" +fi + +if [ -n "$SECRET_VAL" ]; then + # 脱敏显示:前4后4 + MASKED="${SECRET_VAL:0:4}****${SECRET_VAL: -4}" + echo "" + echo "🌐 Dashboard:http://127.0.0.1:9090/ui" + echo "🔐 Secret:${MASKED}" + echo " 查看完整 Secret:sudo awk -F': *' '/^secret:/{print \$2; exit}' $CONF_FILE" else - echo -e "🔐 Secret:请查看 .env 或启动日志输出" + echo "" + echo "🌐 Dashboard:http://127.0.0.1:9090/ui" + echo "🔐 Secret:未读取到(服务首次启动后生成),可用以下命令查看:" + echo " sudo awk -F': *' '/^secret:/{print \$2; exit}' $CONF_FILE" fi echo From 61829f17a1d51747516e23b0a56cc8e12280e345 Mon Sep 17 00:00:00 2001 From: wnlen <62139570+wnlen@users.noreply.github.com> Date: Wed, 14 Jan 2026 23:29:01 +0800 Subject: [PATCH 15/20] Update install.sh --- install.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/install.sh b/install.sh index 69eb725..46f7e74 100755 --- a/install.sh +++ b/install.sh @@ -239,7 +239,6 @@ api_host="${EXTERNAL_CONTROLLER%:*}" if [ -z "$api_host" ] || [ "$api_host" = "$EXTERNAL_CONTROLLER" ]; then api_host="127.0.0.1" fi -echo -e "🌐 Dashboard:http://${api_host}:${api_port}/ui" # ---- Secret 展示(脱敏)---- CONF_DIR="${CLASH_INSTALL_DIR:-/opt/clash-for-linux}/conf" @@ -255,12 +254,12 @@ if [ -n "$SECRET_VAL" ]; then # 脱敏显示:前4后4 MASKED="${SECRET_VAL:0:4}****${SECRET_VAL: -4}" echo "" - echo "🌐 Dashboard:http://127.0.0.1:9090/ui" + echo -e "🌐 Dashboard:http://${api_host}:${api_port}/ui" echo "🔐 Secret:${MASKED}" echo " 查看完整 Secret:sudo awk -F': *' '/^secret:/{print \$2; exit}' $CONF_FILE" else echo "" - echo "🌐 Dashboard:http://127.0.0.1:9090/ui" + echo -e "🌐 Dashboard:http://${api_host}:${api_port}/ui" echo "🔐 Secret:未读取到(服务首次启动后生成),可用以下命令查看:" echo " sudo awk -F': *' '/^secret:/{print \$2; exit}' $CONF_FILE" fi From b0a5a9a6bfaa69c116cfd24a23449de7c9dd45f9 Mon Sep 17 00:00:00 2001 From: wnlen <62139570+wnlen@users.noreply.github.com> Date: Wed, 14 Jan 2026 23:37:27 +0800 Subject: [PATCH 16/20] Update install.sh --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 46f7e74..fc400fa 100755 --- a/install.sh +++ b/install.sh @@ -260,7 +260,7 @@ if [ -n "$SECRET_VAL" ]; then else echo "" echo -e "🌐 Dashboard:http://${api_host}:${api_port}/ui" - echo "🔐 Secret:未读取到(服务首次启动后生成),可用以下命令查看:" + echo "🔐 Secret:未配置(当前为无鉴权模式,仅限本机访问),可用以下命令查看:" echo " sudo awk -F': *' '/^secret:/{print \$2; exit}' $CONF_FILE" fi From f3ef39f7366a04542644c226c8a4030bc9ce2f8e Mon Sep 17 00:00:00 2001 From: wnlen <62139570+wnlen@users.noreply.github.com> Date: Wed, 14 Jan 2026 23:37:54 +0800 Subject: [PATCH 17/20] Update .env --- .env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env b/.env index c120385..8d12e89 100644 --- a/.env +++ b/.env @@ -32,7 +32,7 @@ export CLASH_SUBSCRIPTION='' export CLASH_SECRET='' # 是否在启动输出中显示完整 Secret(不推荐) -CLASH_SHOW_SECRET=false +CLASH_SHOW_SECRET=true # 是否显示脱敏 Secret(推荐) CLASH_SHOW_SECRET_MASKED=true From 6e172ce01b75d4bc0eabe742ab2c440bc9cb641e Mon Sep 17 00:00:00 2001 From: wnlen <62139570+wnlen@users.noreply.github.com> Date: Thu, 15 Jan 2026 00:06:38 +0800 Subject: [PATCH 18/20] Update config.yaml --- conf/config.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/conf/config.yaml b/conf/config.yaml index 9a88d18..aa1b75d 100644 --- a/conf/config.yaml +++ b/conf/config.yaml @@ -7,6 +7,8 @@ ipv6: true udp: true external-controller: 127.0.0.1:9090 +external-ui: /opt/clash-for-linux/dashboard/public +secret: "" proxies: [] proxy-groups: [] @@ -14,3 +16,4 @@ proxy-groups: [] rules: - MATCH,DIRECT + From 0865d540c51d853b1765e430e1502243a47a7a02 Mon Sep 17 00:00:00 2001 From: wnlen <62139570+wnlen@users.noreply.github.com> Date: Thu, 15 Jan 2026 00:07:02 +0800 Subject: [PATCH 19/20] Update config.yaml --- conf/config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/conf/config.yaml b/conf/config.yaml index aa1b75d..ab9cb7c 100644 --- a/conf/config.yaml +++ b/conf/config.yaml @@ -17,3 +17,4 @@ rules: - MATCH,DIRECT + From 34ff735ee1f66ec7ea582eefe0761c3a359487cc Mon Sep 17 00:00:00 2001 From: wnlen <62139570+wnlen@users.noreply.github.com> Date: Thu, 15 Jan 2026 00:07:15 +0800 Subject: [PATCH 20/20] Update fallback_config.yaml --- conf/fallback_config.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/conf/fallback_config.yaml b/conf/fallback_config.yaml index 378f798..250c095 100644 --- a/conf/fallback_config.yaml +++ b/conf/fallback_config.yaml @@ -7,6 +7,8 @@ ipv6: true udp: true external-controller: 127.0.0.1:9090 +external-ui: /opt/clash-for-linux/dashboard/public +secret: "" proxies: [] proxy-groups: []